Version 0.8.4.0 .

svn merge -r 28767:28907 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@28908 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/client/tools/buildbot_annotated_steps.py b/client/tools/buildbot_annotated_steps.py
index 21f2e48..a6f1c1f 100755
--- a/client/tools/buildbot_annotated_steps.py
+++ b/client/tools/buildbot_annotated_steps.py
@@ -15,7 +15,6 @@
 
 import imp
 import os
-import platform
 import re
 import socket
 import subprocess
@@ -88,6 +87,8 @@
 
   toolsBuildScript = os.path.join('.', 'editor', 'build', 'build.py')
 
+  build_installer = name.startswith('dart-editor-installer')
+
   # TODO(devoncarew): should we move this into GetBuildInfo()?
   # get the latest changed revision from the current repository sub-tree
   version = GetLatestChangedRevision()
@@ -96,6 +97,8 @@
   cmds = [sys.executable, toolsBuildScript,
           '--mode=' + mode, '--revision=' + version,
           '--name=' + name, '--out=' + outdir]
+  if build_installer:
+    cmds.append('--build-installer')
   local_env = EnvironmentWithoutBotoConfig()
   #if 'linux' in name:
   #  javahome = os.path.join(os.path.expanduser('~'), 'jdk1.6.0_25')
@@ -135,10 +138,7 @@
   buildbot_javahome = os.getenv('BUILDBOT_JAVA_HOME')
   if buildbot_javahome:
     current_pwd = os.getenv('PWD')
-    if platform.system() != 'Windows':
-      java_home = '/usr/lib/jvm/java-6-sun' # Hackety-hack. Please remove!
-    else:
-      java_home = os.path.join(current_pwd, buildbot_javahome)
+    java_home = os.path.join(current_pwd, buildbot_javahome)
     java_bin = os.path.join(java_home, 'bin')
     os.environ['JAVA_HOME'] = java_home
     os.environ['PATH'] = '%s;%s' % (java_bin, os.environ['PATH'])
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index f477b94..4d98d9e 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -641,6 +641,17 @@
 
 If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$. 
 
+\commentary {
+A consequence of these rules is that it is possible to hide a type with a method or variable.
+Naming conventions usually prevent such abuses. Nevertheless,the following program is legal:
+}
+
+\begin{dartCode}
+\CLASS{} HighlyStrung \{
+  String() $=>$ "?";
+\}
+\end{dartCode}
+
 Names may be introduced into a scope by  declarations within the scope or  by other mechanisms such as imports or inheritance.
 
 \rationale{
@@ -815,7 +826,11 @@
 
 A library variable introduces a getter and a setter into the top level scope of the enclosing library. A static class variable introduces a static getter and a static setter into the immediately enclosing class. An instance variable introduces an instance getter and an instance setter into the immediately enclosing class. 
 
-Local variables are added to the innermost enclosing scope.  They do not induce getters and setters.  A local variable may only be referenced at a source code location that is after its initializer, if any, is complete, or a a compile-time error occurs. 
+Local variables are added to the innermost enclosing scope.  They do not induce getters and setters.  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.  The error may be reported either at the point where the premature reference occurs, or at the variable declaration.
+
+\rationale {
+We allow the error to be reported at the declaration to allow implementations to avoid an extra processing phase. 
+}
 
 \commentary{
 The example below illustrates the expected behavior.  A variable $x$ is declared at the library level, and another $x$ is declared inside the function $f$.
@@ -842,10 +857,29 @@
 }
 
 \commentary {
-As another example  \code{var x = 3, y = x;} is legal, because \code{x} is referenced after its initializer. 
+As another example  \code{\VAR{} x = 3, y = x;} is legal, because \code{x} is referenced after its initializer. 
 
+A particularly perverse example involves a local variable name shadowing a type. This is possible because Dart has a single namespace for types, functions and variables.
 }
 
+\begin{dartCode}
+\CLASS{} C \{\}
+perverse() \{
+   \VAR{} v = \NEW{} C(); // compile-time error
+   C aC; // compile-time error
+   \VAR{} C = 10;
+\}
+
+\commentary {
+ Inside \cd{perverse()}, \cd{C} denotes a local variable. The type \cd{C} is hidden by the variable of the same name. The attempt to instantiate \cd{C} causes a compile-time error because it references a local variable prior to its declaration. Similarly, for the declaration of \cd{aC} (even though it is only a type annotation).
+}
+
+\rationale{
+As a rule, type annotations are ignored in production mode. However, we do not want to allow programs to compile legally in one mode and not another, and in this extremely odd situation, that consideration takes precedence.
+}
+
+\end{dartCode}
+
 % the grammar does not support local getters and setters. The local var discussion does not seem to mention getters and setters based semantics. It simply discusses the creation of the variable, not its access. Access is either assignment or identifiers. Identifiers ignore the getter story. 
 
 The following rules apply to all static and instance variables.
@@ -1468,7 +1502,7 @@
 
 %whose execution sets the value of $v$ to the incoming argument $x$.
 
-% It is a compile-time error/warning if a a class $C$ declares a final instance variable $v$ and $C$ inherits a setter $v=$.
+% It is a compile-time error/warning if a class $C$ declares a final instance variable $v$ and $C$ inherits a setter $v=$.
 
 
 \subsection{Constructors}
@@ -2140,7 +2174,12 @@
 \end{itemize}
 
 
-Let $I$ be the implicit interface of a class $C$ declared in library $L$.  $I$ {\em inherits} all members of $inherited(I, L)$ and $I$ {\em overrides} $m^\prime$ if  $m^\prime \in overrides(I, L)$. It is a static warning if $m$ is a method and $m^\prime$ is a getter, or if $m$ is a getter and $m^\prime$ is a method.
+Let $I$ be the implicit interface of a class $C$ declared in library $L$.  $I$ {\em inherits} all members of $inherited(I, L)$ and $I$ {\em overrides} $m^\prime$ if  $m^\prime \in overrides(I, L)$. 
+
+All the static warnings pertaining to the overriding of instance members given in section \ref{classes} above hold for overriding between interfaces as well.
+
+It is a static warning if $m$ is a method and $m^\prime$ is a getter, or if $m$ is a getter and $m^\prime$ is a method.
+
 
 
 %Let $I = S_0$ be the implicit interface of a class $C$ declared in library $L$, and let $\{S_1 \ldots S_k\}$ be the set of all superinterfaces of $I$. 
@@ -5984,6 +6023,7 @@
 \subsubsection{Least Upper Bounds}
 \label{leastUpperBounds}
 
+% does this diverge in some cases?
 Given two interfaces $I$ and $J$, let $S_I$ be the set of superinterfaces of $I$,  let $S_J$ be the set of superinterfaces of $J$ and let $S =  (I \cup S_I) \cap (J \cup S_J)$.  Furthermore, we define $S_n = \{T | T \in S  \wedge depth(T) =n\}$ for any finite $n$ %, and $k=max(depth(T_1), \ldots, depth(T_m)), T_i \in S, i \in 1..m$, 
 where $depth(T)$ is the number of steps in the longest inheritance path from $T$ to \code{Object}. Let $q$ be the largest number such that $S_q$ has cardinality one. The least upper bound of $I$ and $J$ is the sole element of  $S_q$.
 
diff --git a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
index 2104617..c7beef7 100644
--- a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
@@ -48,7 +48,8 @@
       throw new ArgumentError("sourcePath cannot be null");
     }
     var sourceFile = new JavaFile(sourcePath);
-    var librarySource = new FileBasedSource.con1(contentCache, sourceFile);
+    var uriKind = getUriKind(sourceFile);
+    var librarySource = new FileBasedSource.con2(contentCache, sourceFile, uriKind);
     // resolve library
     prepareAnalysisContext(sourceFile);
     var libraryElement = context.computeLibraryElement(librarySource);
@@ -89,6 +90,7 @@
 
     // set options for context
     AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
+    contextOptions.cacheSize = 256;
     contextOptions.hint = !options.disableHints;
     context.analysisOptions = contextOptions;
   }
@@ -165,4 +167,22 @@
     // not found
     return null;
   }
+
+  /**
+   * Returns the [UriKind] for the given input file. Usually {@link UriKind#FILE_URI}, but if
+   * the given file is located in the "lib" directory of the [sdk], then returns
+   * {@link UriKind#DART_URI}.
+   */
+  static UriKind getUriKind(JavaFile file) {
+    // may be file in SDK
+    if (sdk is DirectoryBasedDartSdk) {
+      DirectoryBasedDartSdk directoryBasedSdk = sdk;
+      String sdkLibPath = directoryBasedSdk.libraryDirectory.getPath() + JavaFile.separator;
+      if (file.getPath().startsWith(sdkLibPath)) {
+        return UriKind.DART_URI;
+      }
+    }
+    // some generic file
+    return UriKind.FILE_URI;
+  }
 }
diff --git a/pkg/analyzer_experimental/lib/src/generated/ast.dart b/pkg/analyzer_experimental/lib/src/generated/ast.dart
index 196b4e8..e377a46 100644
--- a/pkg/analyzer_experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/ast.dart
@@ -4,7 +4,6 @@
 import 'dart:collection';
 import 'java_core.dart';
 import 'java_engine.dart';
-import 'error.dart';
 import 'source.dart' show LineInfo;
 import 'scanner.dart';
 import 'engine.dart' show AnalysisEngine;
@@ -2785,21 +2784,6 @@
   LineInfo lineInfo;
 
   /**
-   * The parsing errors encountered when the receiver was parsed.
-   */
-  List<AnalysisError> _parsingErrors = AnalysisError.NO_ERRORS;
-
-  /**
-   * The resolution errors encountered when the receiver was resolved.
-   */
-  List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
-
-  /**
-   * The hints reported when the receiver was analyzed.
-   */
-  List<AnalysisError> _hints = AnalysisError.NO_ERRORS;
-
-  /**
    * Initialize a newly created compilation unit to have the given directives and declarations.
    *
    * @param beginToken the first token in the token stream
@@ -2831,39 +2815,6 @@
   accept(ASTVisitor visitor) => visitor.visitCompilationUnit(this);
   Token get beginToken => _beginToken;
   Token get endToken => _endToken;
-
-  /**
-   * Return an array containing all of the errors associated with the receiver. The array will be
-   * empty if the receiver has not been resolved and there were no parse errors.
-   *
-   * @return the errors associated with the receiver
-   */
-  List<AnalysisError> get errors {
-    List<AnalysisError> parserErrors = parsingErrors;
-    List<AnalysisError> resolverErrors = resolutionErrors;
-    List<AnalysisError> hints = this.hints;
-    if (resolverErrors.length == 0 && hints.length == 0) {
-      return parserErrors;
-    } else if (parserErrors.length == 0 && hints.length == 0) {
-      return resolverErrors;
-    } else if (parserErrors.length == 0 && resolverErrors.length == 0) {
-      return hints;
-    } else {
-      List<AnalysisError> allErrors = new List<AnalysisError>(parserErrors.length + resolverErrors.length + hints.length);
-      JavaSystem.arraycopy(parserErrors, 0, allErrors, 0, parserErrors.length);
-      JavaSystem.arraycopy(resolverErrors, 0, allErrors, parserErrors.length, resolverErrors.length);
-      JavaSystem.arraycopy(hints, 0, allErrors, parserErrors.length + resolverErrors.length, hints.length);
-      return allErrors;
-    }
-  }
-
-  /**
-   * Return an array containing all of the hints associated with the receiver. The array will be
-   * empty if the receiver has not been analyzed.
-   *
-   * @return the hints associated with the receiver
-   */
-  List<AnalysisError> get hints => _hints;
   int get length {
     Token endToken = this.endToken;
     if (endToken == null) {
@@ -2874,21 +2825,6 @@
   int get offset => 0;
 
   /**
-   * Return an array containing all of the parsing errors associated with the receiver.
-   *
-   * @return the parsing errors associated with the receiver
-   */
-  List<AnalysisError> get parsingErrors => _parsingErrors;
-
-  /**
-   * Return an array containing all of the resolution errors associated with the receiver. The array
-   * will be empty if the receiver has not been resolved.
-   *
-   * @return the resolution errors associated with the receiver
-   */
-  List<AnalysisError> get resolutionErrors => _resolutionErrors;
-
-  /**
    * Return the script tag at the beginning of the compilation unit, or `null` if there is no
    * script tag in this compilation unit.
    *
@@ -2897,33 +2833,6 @@
   ScriptTag get scriptTag => _scriptTag;
 
   /**
-   * Set the reported hints associated with this compilation unit.
-   *
-   * @param the hints to be associated with this compilation unit
-   */
-  void set hints(List<AnalysisError> errors) {
-    _hints = errors == null ? AnalysisError.NO_ERRORS : errors;
-  }
-
-  /**
-   * Set the parse errors associated with this compilation unit to the given errors.
-   *
-   * @param the parse errors to be associated with this compilation unit
-   */
-  void set parsingErrors(List<AnalysisError> errors) {
-    _parsingErrors = errors == null ? AnalysisError.NO_ERRORS : errors;
-  }
-
-  /**
-   * Set the resolution errors associated with this compilation unit to the given errors.
-   *
-   * @param the resolution errors to be associated with this compilation unit
-   */
-  void set resolutionErrors(List<AnalysisError> errors) {
-    _resolutionErrors = errors == null ? AnalysisError.NO_ERRORS : errors;
-  }
-
-  /**
    * Set the script tag at the beginning of the compilation unit to the given script tag.
    *
    * @param scriptTag the script tag at the beginning of the compilation unit
@@ -4028,7 +3937,7 @@
    * The element associated with this directive, or `null` if the AST structure has not been
    * resolved or if this directive could not be resolved.
    */
-  Element element;
+  Element _element;
 
   /**
    * Initialize a newly create directive.
@@ -4047,12 +3956,30 @@
   Directive({Comment comment, List<Annotation> metadata}) : this.full(comment, metadata);
 
   /**
+   * Return the element associated with this directive, or `null` if the AST structure has not
+   * been resolved or if this directive could not be resolved. Examples of the latter case include a
+   * directive that contains an invalid URL or a URL that does not exist.
+   *
+   * @return the element associated with this directive
+   */
+  Element get element => _element;
+
+  /**
    * Return the token representing the keyword that introduces this directive ('import', 'export',
    * 'library' or 'part').
    *
    * @return the token representing the keyword that introduces this directive
    */
   Token get keyword;
+
+  /**
+   * Set the element associated with this directive to the given element.
+   *
+   * @param element the element associated with this directive
+   */
+  void set element(Element element) {
+    this._element = element;
+  }
 }
 /**
  * Instances of the class `DoStatement` represent a do statement.
@@ -6715,6 +6642,7 @@
    */
   ImportDirective({Comment comment, List<Annotation> metadata, Token keyword, StringLiteral libraryUri, Token asToken, SimpleIdentifier prefix, List<Combinator> combinators, Token semicolon}) : this.full(comment, metadata, keyword, libraryUri, asToken, prefix, combinators, semicolon);
   accept(ASTVisitor visitor) => visitor.visitImportDirective(this);
+  ImportElement get element => super.element as ImportElement;
 
   /**
    * Return the prefix to be used with the imported names, or `null` if the imported names are
@@ -6724,11 +6652,11 @@
    */
   SimpleIdentifier get prefix => _prefix;
   LibraryElement get uriElement {
-    Element element = this.element;
-    if (element is ImportElement) {
-      return ((element as ImportElement)).importedLibrary;
+    ImportElement element = this.element;
+    if (element == null) {
+      return null;
     }
-    return null;
+    return element.importedLibrary;
   }
 
   /**
@@ -12934,7 +12862,7 @@
  *
  * @coverage dart.engine.ast
  */
-class NodeLocator extends GeneralizingASTVisitor<Object> {
+class NodeLocator extends UnifyingASTVisitor<Object> {
 
   /**
    * The start offset of the range used to identify the node.
@@ -13688,7 +13616,7 @@
     return null;
   }
   Object visitClassTypeAlias(ClassTypeAlias node) {
-    _writer.print("typedef ");
+    _writer.print("class ");
     visit(node.name);
     visit(node.typeParameters);
     _writer.print(" = ");
@@ -14425,6 +14353,127 @@
   }
 }
 /**
+ * Instances of the class `UnifyingASTVisitor` implement an AST visitor that will recursively
+ * visit all of the nodes in an AST structure (like instances of the class
+ * [RecursiveASTVisitor]). In addition, every node will also be visited by using a single
+ * unified [visitNode] method.
+ *
+ * Subclasses that override a visit method must either invoke the overridden visit method or
+ * explicitly invoke the more general [visitNode] method. Failure to do so will
+ * cause the children of the visited node to not be visited.
+ *
+ * @coverage dart.engine.ast
+ */
+class UnifyingASTVisitor<R> implements ASTVisitor<R> {
+  R visitAdjacentStrings(AdjacentStrings node) => visitNode(node);
+  R visitAnnotation(Annotation node) => visitNode(node);
+  R visitArgumentDefinitionTest(ArgumentDefinitionTest node) => visitNode(node);
+  R visitArgumentList(ArgumentList node) => visitNode(node);
+  R visitAsExpression(AsExpression node) => visitNode(node);
+  R visitAssertStatement(AssertStatement node) => visitNode(node);
+  R visitAssignmentExpression(AssignmentExpression node) => visitNode(node);
+  R visitBinaryExpression(BinaryExpression node) => visitNode(node);
+  R visitBlock(Block node) => visitNode(node);
+  R visitBlockFunctionBody(BlockFunctionBody node) => visitNode(node);
+  R visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
+  R visitBreakStatement(BreakStatement node) => visitNode(node);
+  R visitCascadeExpression(CascadeExpression node) => visitNode(node);
+  R visitCatchClause(CatchClause node) => visitNode(node);
+  R visitClassDeclaration(ClassDeclaration node) => visitNode(node);
+  R visitClassTypeAlias(ClassTypeAlias node) => visitNode(node);
+  R visitComment(Comment node) => visitNode(node);
+  R visitCommentReference(CommentReference node) => visitNode(node);
+  R visitCompilationUnit(CompilationUnit node) => visitNode(node);
+  R visitConditionalExpression(ConditionalExpression node) => visitNode(node);
+  R visitConstructorDeclaration(ConstructorDeclaration node) => visitNode(node);
+  R visitConstructorFieldInitializer(ConstructorFieldInitializer node) => visitNode(node);
+  R visitConstructorName(ConstructorName node) => visitNode(node);
+  R visitContinueStatement(ContinueStatement node) => visitNode(node);
+  R visitDeclaredIdentifier(DeclaredIdentifier node) => visitNode(node);
+  R visitDefaultFormalParameter(DefaultFormalParameter node) => visitNode(node);
+  R visitDoStatement(DoStatement node) => visitNode(node);
+  R visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
+  R visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
+  R visitEmptyStatement(EmptyStatement node) => visitNode(node);
+  R visitExportDirective(ExportDirective node) => visitNode(node);
+  R visitExpressionFunctionBody(ExpressionFunctionBody node) => visitNode(node);
+  R visitExpressionStatement(ExpressionStatement node) => visitNode(node);
+  R visitExtendsClause(ExtendsClause node) => visitNode(node);
+  R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
+  R visitFieldFormalParameter(FieldFormalParameter node) => visitNode(node);
+  R visitForEachStatement(ForEachStatement node) => visitNode(node);
+  R visitFormalParameterList(FormalParameterList node) => visitNode(node);
+  R visitForStatement(ForStatement node) => visitNode(node);
+  R visitFunctionDeclaration(FunctionDeclaration node) => visitNode(node);
+  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) => visitNode(node);
+  R visitFunctionExpression(FunctionExpression node) => visitNode(node);
+  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) => visitNode(node);
+  R visitFunctionTypeAlias(FunctionTypeAlias node) => visitNode(node);
+  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) => visitNode(node);
+  R visitHideCombinator(HideCombinator node) => visitNode(node);
+  R visitIfStatement(IfStatement node) => visitNode(node);
+  R visitImplementsClause(ImplementsClause node) => visitNode(node);
+  R visitImportDirective(ImportDirective node) => visitNode(node);
+  R visitIndexExpression(IndexExpression node) => visitNode(node);
+  R visitInstanceCreationExpression(InstanceCreationExpression node) => visitNode(node);
+  R visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
+  R visitInterpolationExpression(InterpolationExpression node) => visitNode(node);
+  R visitInterpolationString(InterpolationString node) => visitNode(node);
+  R visitIsExpression(IsExpression node) => visitNode(node);
+  R visitLabel(Label node) => visitNode(node);
+  R visitLabeledStatement(LabeledStatement node) => visitNode(node);
+  R visitLibraryDirective(LibraryDirective node) => visitNode(node);
+  R visitLibraryIdentifier(LibraryIdentifier node) => visitNode(node);
+  R visitListLiteral(ListLiteral node) => visitNode(node);
+  R visitMapLiteral(MapLiteral node) => visitNode(node);
+  R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
+  R visitMethodDeclaration(MethodDeclaration node) => visitNode(node);
+  R visitMethodInvocation(MethodInvocation node) => visitNode(node);
+  R visitNamedExpression(NamedExpression node) => visitNode(node);
+  R visitNativeClause(NativeClause node) => visitNode(node);
+  R visitNativeFunctionBody(NativeFunctionBody node) => visitNode(node);
+  R visitNode(ASTNode node) {
+    node.visitChildren(this);
+    return null;
+  }
+  R visitNullLiteral(NullLiteral node) => visitNode(node);
+  R visitParenthesizedExpression(ParenthesizedExpression node) => visitNode(node);
+  R visitPartDirective(PartDirective node) => visitNode(node);
+  R visitPartOfDirective(PartOfDirective node) => visitNode(node);
+  R visitPostfixExpression(PostfixExpression node) => visitNode(node);
+  R visitPrefixedIdentifier(PrefixedIdentifier node) => visitNode(node);
+  R visitPrefixExpression(PrefixExpression node) => visitNode(node);
+  R visitPropertyAccess(PropertyAccess node) => visitNode(node);
+  R visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) => visitNode(node);
+  R visitRethrowExpression(RethrowExpression node) => visitNode(node);
+  R visitReturnStatement(ReturnStatement node) => visitNode(node);
+  R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
+  R visitShowCombinator(ShowCombinator node) => visitNode(node);
+  R visitSimpleFormalParameter(SimpleFormalParameter node) => visitNode(node);
+  R visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
+  R visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
+  R visitStringInterpolation(StringInterpolation node) => visitNode(node);
+  R visitSuperConstructorInvocation(SuperConstructorInvocation node) => visitNode(node);
+  R visitSuperExpression(SuperExpression node) => visitNode(node);
+  R visitSwitchCase(SwitchCase node) => visitNode(node);
+  R visitSwitchDefault(SwitchDefault node) => visitNode(node);
+  R visitSwitchStatement(SwitchStatement node) => visitNode(node);
+  R visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
+  R visitThisExpression(ThisExpression node) => visitNode(node);
+  R visitThrowExpression(ThrowExpression node) => visitNode(node);
+  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) => visitNode(node);
+  R visitTryStatement(TryStatement node) => visitNode(node);
+  R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
+  R visitTypeName(TypeName node) => visitNode(node);
+  R visitTypeParameter(TypeParameter node) => visitNode(node);
+  R visitTypeParameterList(TypeParameterList node) => visitNode(node);
+  R visitVariableDeclaration(VariableDeclaration node) => visitNode(node);
+  R visitVariableDeclarationList(VariableDeclarationList node) => visitNode(node);
+  R visitVariableDeclarationStatement(VariableDeclarationStatement node) => visitNode(node);
+  R visitWhileStatement(WhileStatement node) => visitNode(node);
+  R visitWithClause(WithClause node) => visitNode(node);
+}
+/**
  * Instances of the class `ASTCloner` implement an object that will clone any AST structure
  * that it visits. The cloner will only clone the structure, it will not preserve any resolution
  * results or properties associated with the nodes.
@@ -14462,9 +14511,6 @@
   CompilationUnit visitCompilationUnit(CompilationUnit node) {
     CompilationUnit clone = new CompilationUnit.full(node.beginToken, clone2(node.scriptTag), clone3(node.directives), clone3(node.declarations), node.endToken);
     clone.lineInfo = node.lineInfo;
-    clone.parsingErrors = node.parsingErrors;
-    clone.resolutionErrors = node.resolutionErrors;
-    clone.hints = node.hints;
     return clone;
   }
   ConditionalExpression visitConditionalExpression(ConditionalExpression node) => new ConditionalExpression.full(clone2(node.condition), node.question, clone2(node.thenExpression), node.colon, clone2(node.elseExpression));
@@ -14723,67 +14769,132 @@
 /**
  * Instances of the class {@code NodeList} represent a list of AST nodes that have a common parent.
  */
-class NodeList<E extends ASTNode> extends ListWrapper<E> {
+class NodeList<E extends ASTNode> extends Object with ListMixin<E> {
+  /**
+   * Create an empty list with the given owner. This is a convenience method that allows the
+   * compiler to determine the correct value of the type argument [E] without needing to
+   * explicitly specify it.
+   *
+   * @param owner the node that is the parent of each of the elements in the list
+   * @return the list that was created
+   */
+  static NodeList create(ASTNode owner) => new NodeList(owner);
+
   /**
    * The node that is the parent of each of the elements in the list.
    */
   ASTNode owner;
+
   /**
-   * The elements of the list.
+   * The elements contained in the list.
    */
-  List<E> elements = new List<E>();
+  List<E> _elements = <E> [];
+
   /**
    * Initialize a newly created list of nodes to be empty.
+   *
    * @param owner the node that is the parent of each of the elements in the list
    */
-  NodeList(ASTNode this.owner);
+  NodeList(this.owner);
+
   /**
    * Use the given visitor to visit each of the nodes in this list.
+   *
    * @param visitor the visitor to be used to visit the elements of this list
    */
   accept(ASTVisitor visitor) {
-    for (E element in elements) {
+    for (E element in _elements) {
       element.accept(visitor);
     }
   }
   void add(E node) {
+    insert(length, node);
+  }
+  void insert(int index, E node) {
+    int length = _elements.length;
+    if (index < 0 || index > length) {
+      throw new RangeError("Index: ${index}, Size: ${_elements.length}");
+    }
     owner.becomeParentOf(node);
-    elements.add(node);
+    if (length == 0) {
+      _elements = <E> [node];
+    } else {
+      List<E> newElements = new List<E>(length + 1);
+      JavaSystem.arraycopy(_elements, 0, newElements, 0, index);
+      newElements[index] = node;
+      JavaSystem.arraycopy(_elements, index, newElements, index + 1, length - index);
+      _elements = newElements;
+    }
   }
   bool addAll(Iterable<E> nodes) {
-    if (nodes != null) {
+    if (nodes != null && !nodes.isEmpty) {
+      int oldCount = _elements.length;
+      int newCount = nodes.length;
+      List<E> newElements = new List<E>(oldCount + newCount);
+      JavaSystem.arraycopy(_elements, 0, newElements, 0, oldCount);
+      int index = oldCount;
       for (E node in nodes) {
-        add(node);
+        owner.becomeParentOf(node);
+        newElements[index++] = node;
       }
+      _elements = newElements;
       return true;
     }
     return false;
   }
+  E operator[](int index) {
+    if (index < 0 || index >= _elements.length) {
+      throw new RangeError("Index: ${index}, Size: ${_elements.length}");
+    }
+    return _elements[index] as E;
+  }
+
   /**
    * Return the first token included in this node's source range.
+   *
    * @return the first token included in this node's source range
    */
   Token get beginToken {
-    if (elements.isEmpty) {
+    if (_elements.length == 0) {
       return null;
     }
-    return elements[0].beginToken;
+    return _elements[0].beginToken;
   }
+
   /**
    * Return the last token included in this node list's source range.
+   *
    * @return the last token included in this node list's source range
    */
   Token get endToken {
-    if (elements.isEmpty) {
+    if (_elements.length == 0) {
       return null;
     }
-    return elements[elements.length - 1].endToken;
+    return _elements[_elements.length - 1].endToken;
   }
-  /**
-   * Return the node that is the parent of each of the elements in the list.
-   * @return the node that is the parent of each of the elements in the list
-   */
-  ASTNode getOwner() {
-    return owner;
+  E removeAt(int index) {
+    if (index < 0 || index >= _elements.length) {
+      throw new RangeError("Index: ${index}, Size: ${_elements.length}");
+    }
+    E removedNode = _elements[index] as E;
+    int length = _elements.length;
+    if (length == 1) {
+      _elements = ASTNode.EMPTY_ARRAY;
+      return removedNode;
+    }
+    List<E> newElements = new List<E>(length - 1);
+    JavaSystem.arraycopy(_elements, 0, newElements, 0, index);
+    JavaSystem.arraycopy(_elements, index + 1, newElements, index, length - index - 1);
+    _elements = newElements;
+    return removedNode;
   }
+  void operator[]=(int index, E node) {
+    if (index < 0 || index >= _elements.length) {
+      throw new RangeError("Index: ${index}, Size: ${_elements.length}");
+    }
+    _elements[index] as E;
+    owner.becomeParentOf(node);
+    _elements[index] = node;
+  }
+  int get length => _elements.length;
 }
diff --git a/pkg/analyzer_experimental/lib/src/generated/constant.dart b/pkg/analyzer_experimental/lib/src/generated/constant.dart
index 7036abb..12b536f 100644
--- a/pkg/analyzer_experimental/lib/src/generated/constant.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/constant.dart
@@ -292,7 +292,7 @@
  *
  * </blockquote>
  */
-class ConstantVisitor extends GeneralizingASTVisitor<EvaluationResultImpl> {
+class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> {
   EvaluationResultImpl visitAdjacentStrings(AdjacentStrings node) {
     EvaluationResultImpl result = null;
     for (StringLiteral string in node.strings) {
@@ -970,7 +970,7 @@
    * A result object representing the an arbitrary integer on which no further operations can be
    * performed.
    */
-  static ValidResult RESULT_INT = new ValidResult(null);
+  static ValidResult RESULT_INT = new ValidResult(0);
 
   /**
    * A result object representing the `null` value.
@@ -1096,6 +1096,12 @@
       return valueOf4(((value as double)).toString());
     } else if (value is String) {
       return this;
+    } else if (isSomeBool) {
+      return valueOf4("<some bool>");
+    } else if (isSomeInt) {
+      return valueOf4("<some int>");
+    } else if (isSomeNum) {
+      return valueOf4("<some num>");
     }
     return error(node);
   }
@@ -1581,7 +1587,7 @@
       return error(node.rightOperand);
     } else if (leftValue is int) {
       if (value is int) {
-        return valueOf(((leftValue as int)) << ((value as int)));
+        return RESULT_INT;
       }
       return error(node.rightOperand);
     }
diff --git a/pkg/analyzer_experimental/lib/src/generated/element.dart b/pkg/analyzer_experimental/lib/src/generated/element.dart
index 067b214..06744c1 100644
--- a/pkg/analyzer_experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/element.dart
@@ -1319,6 +1319,13 @@
   bool get isAbstract;
 
   /**
+   * Return `true` if this setter for final variable, so it causes warning when used.
+   *
+   * @return `true` if this accessor is excluded setter
+   */
+  bool get isExcludedSetter;
+
+  /**
    * Return `true` if this accessor represents a getter.
    *
    * @return `true` if this accessor represents a getter
@@ -1388,6 +1395,20 @@
 abstract class ShowElementCombinator implements NamespaceCombinator {
 
   /**
+   * Return the offset of the character immediately following the last character of this node.
+   *
+   * @return the offset of the character just past this node
+   */
+  int get end;
+
+  /**
+   * Return the offset of the 'show' keyword of this element.
+   *
+   * @return the offset of the 'show' keyword of this element
+   */
+  int get offset;
+
+  /**
    * Return an array containing the names that are to be made visible in the importing library if
    * they are defined in the imported library.
    *
@@ -4445,6 +4466,57 @@
 class MultiplyDefinedElementImpl implements MultiplyDefinedElement {
 
   /**
+   * Return an element that represents the given conflicting elements.
+   *
+   * @param context the analysis context in which the multiply defined elements are defined
+   * @param firstElement the first element that conflicts
+   * @param secondElement the second element that conflicts
+   */
+  static Element fromElements(AnalysisContext context, Element firstElement, Element secondElement) {
+    List<Element> conflictingElements = computeConflictingElements(firstElement, secondElement);
+    int length = conflictingElements.length;
+    if (length == 0) {
+      return null;
+    } else if (length == 1) {
+      return conflictingElements[0];
+    }
+    return new MultiplyDefinedElementImpl(context, conflictingElements);
+  }
+
+  /**
+   * Add the given element to the list of elements. If the element is a multiply-defined element,
+   * add all of the conflicting elements that it represents.
+   *
+   * @param elements the list to which the element(s) are to be added
+   * @param element the element(s) to be added
+   */
+  static void add(Set<Element> elements, Element element) {
+    if (element is MultiplyDefinedElementImpl) {
+      for (Element conflictingElement in ((element as MultiplyDefinedElementImpl))._conflictingElements) {
+        javaSetAdd(elements, conflictingElement);
+      }
+    } else {
+      javaSetAdd(elements, element);
+    }
+  }
+
+  /**
+   * Use the given elements to construct an array of conflicting elements. If either of the given
+   * elements are multiply-defined elements then the conflicting elements they represent will be
+   * included in the array. Otherwise, the element itself will be included.
+   *
+   * @param firstElement the first element to be included
+   * @param secondElement the second element to be included
+   * @return an array containing all of the conflicting elements
+   */
+  static List<Element> computeConflictingElements(Element firstElement, Element secondElement) {
+    Set<Element> elements = new Set<Element>();
+    add(elements, firstElement);
+    add(elements, secondElement);
+    return new List.from(elements);
+  }
+
+  /**
    * The analysis context in which the multiply defined elements are defined.
    */
   AnalysisContext _context;
@@ -4463,22 +4535,9 @@
    * Initialize a newly created element to represent a list of conflicting elements.
    *
    * @param context the analysis context in which the multiply defined elements are defined
-   * @param firstElement the first element that conflicts
-   * @param secondElement the second element that conflicts
-   */
-  MultiplyDefinedElementImpl.con1(AnalysisContext context, Element firstElement, Element secondElement) {
-    this._context = context;
-    _name = firstElement.name;
-    _conflictingElements = computeConflictingElements(firstElement, secondElement);
-  }
-
-  /**
-   * Initialize a newly created element to represent a list of conflicting elements.
-   *
-   * @param context the analysis context in which the multiply defined elements are defined
    * @param conflictingElements the elements that conflict
    */
-  MultiplyDefinedElementImpl.con2(AnalysisContext context, List<Element> conflictingElements) {
+  MultiplyDefinedElementImpl(AnalysisContext context, List<Element> conflictingElements) {
     this._context = context;
     _name = conflictingElements[0].name;
     this._conflictingElements = conflictingElements;
@@ -4522,39 +4581,6 @@
   }
   void visitChildren(ElementVisitor visitor) {
   }
-
-  /**
-   * Add the given element to the list of elements. If the element is a multiply-defined element,
-   * add all of the conflicting elements that it represents.
-   *
-   * @param elements the list to which the element(s) are to be added
-   * @param element the element(s) to be added
-   */
-  void add(Set<Element> elements, Element element) {
-    if (element is MultiplyDefinedElementImpl) {
-      for (Element conflictingElement in ((element as MultiplyDefinedElementImpl))._conflictingElements) {
-        javaSetAdd(elements, conflictingElement);
-      }
-    } else {
-      javaSetAdd(elements, element);
-    }
-  }
-
-  /**
-   * Use the given elements to construct an array of conflicting elements. If either of the given
-   * elements are multiply-defined elements then the conflicting elements they represent will be
-   * included in the array. Otherwise, the element itself will be included.
-   *
-   * @param firstElement the first element to be included
-   * @param secondElement the second element to be included
-   * @return an array containing all of the conflicting elements
-   */
-  List<Element> computeConflictingElements(Element firstElement, Element secondElement) {
-    Set<Element> elements = new Set<Element>();
-    add(elements, firstElement);
-    add(elements, secondElement);
-    return new List.from(elements);
-  }
 }
 /**
  * Instances of the class `ParameterElementImpl` implement a `ParameterElement`.
@@ -4812,6 +4838,7 @@
   }
   PropertyInducingElement get variable => _variable;
   bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+  bool get isExcludedSetter => isSetter && _variable.isFinal;
   bool get isGetter => hasModifier(Modifier.GETTER);
   bool get isSetter => hasModifier(Modifier.SETTER);
   bool get isStatic => hasModifier(Modifier.STATIC);
@@ -4939,9 +4966,35 @@
    * imported library.
    */
   List<String> _shownNames = StringUtilities.EMPTY_ARRAY;
+
+  /**
+   * The offset of the character immediately following the last character of this node.
+   */
+  int _end = -1;
+
+  /**
+   * The offset of the 'show' keyword of this element.
+   */
+  int _offset = 0;
+  int get end => _end;
+  int get offset => _offset;
   List<String> get shownNames => _shownNames;
 
   /**
+   * Set the the offset of the character immediately following the last character of this node.
+   */
+  void set end(int endOffset) {
+    this._end = endOffset;
+  }
+
+  /**
+   * Sets the offset of the 'show' keyword of this directive.
+   */
+  void set offset(int offset) {
+    this._offset = offset;
+  }
+
+  /**
    * Set the names that are to be made visible in the importing library if they are defined in the
    * imported library to the given names.
    *
@@ -5532,12 +5585,14 @@
     if (baseParameter == null || definingType.typeArguments.length == 0) {
       return baseParameter;
     }
-    Type2 baseType = baseParameter.type;
-    List<Type2> argumentTypes = definingType.typeArguments;
-    List<Type2> parameterTypes = TypeParameterTypeImpl.getTypes(definingType.typeParameters);
-    Type2 substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
-    if (baseType == substitutedType) {
-      return baseParameter;
+    if (baseParameter is! FieldFormalParameterElement) {
+      Type2 baseType = baseParameter.type;
+      List<Type2> argumentTypes = definingType.typeArguments;
+      List<Type2> parameterTypes = TypeParameterTypeImpl.getTypes(definingType.typeParameters);
+      Type2 substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
+      if (baseType == substitutedType) {
+        return baseParameter;
+      }
     }
     return new ParameterMember(baseParameter, definingType);
   }
@@ -5662,6 +5717,7 @@
     return variable;
   }
   bool get isAbstract => baseElement.isAbstract;
+  bool get isExcludedSetter => baseElement.isExcludedSetter;
   bool get isGetter => baseElement.isGetter;
   bool get isSetter => baseElement.isSetter;
   String toString() {
@@ -6930,11 +6986,19 @@
   bool operator ==(Object object) => object is TypeParameterTypeImpl && element == ((object as TypeParameterTypeImpl)).element;
   TypeParameterElement get element => super.element as TypeParameterElement;
   int get hashCode => element.hashCode;
-  bool isMoreSpecificThan(Type2 type) {
-    Type2 upperBound = element.bound;
-    return type == upperBound;
+  bool isMoreSpecificThan(Type2 s) {
+    if (this == s) {
+      return true;
+    }
+    if (s.isBottom) {
+      return true;
+    }
+    if (s.isDynamic) {
+      return true;
+    }
+    return isMoreSpecificThan3(s, new Set<Type2>());
   }
-  bool isSubtypeOf(Type2 type) => true;
+  bool isSubtypeOf(Type2 s) => isMoreSpecificThan(s);
   Type2 substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) {
     int length = parameterTypes.length;
     for (int i = 0; i < length; i++) {
@@ -6944,6 +7008,27 @@
     }
     return this;
   }
+  bool isMoreSpecificThan3(Type2 s, Set<Type2> visitedTypes) {
+    Type2 bound = element.bound;
+    if (s == bound) {
+      return true;
+    }
+    if (s.isObject) {
+      return true;
+    }
+    if (bound == null) {
+      return false;
+    }
+    if (bound is TypeParameterTypeImpl) {
+      TypeParameterTypeImpl boundTypeParameter = bound as TypeParameterTypeImpl;
+      if (visitedTypes.contains(bound)) {
+        return false;
+      }
+      javaSetAdd(visitedTypes, bound);
+      return boundTypeParameter.isMoreSpecificThan3(s, visitedTypes);
+    }
+    return bound.isMoreSpecificThan(s);
+  }
 }
 /**
  * The unique instance of the class `VoidTypeImpl` implements the type `void`.
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
index 603223b..3217940 100644
--- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -269,7 +269,9 @@
   AnalysisContext extractContext(SourceContainer container);
 
   /**
-   * Return the set of analysis options controlling the behavior of this context.
+   * Return the set of analysis options controlling the behavior of this context. Clients should not
+   * modify the returned set of options. The options should only be set by invoking the method
+   * [setAnalysisOptions].
    *
    * @return the set of analysis options controlling the behavior of this context
    */
@@ -414,6 +416,15 @@
   LineInfo getLineInfo(Source source);
 
   /**
+   * Return an array containing all of the sources known to this context and their resolution state
+   * is not valid or flush. So, these sources are not safe to update during refactoring, because we
+   * may be don't know all the references in them.
+   *
+   * @return the sources known to this context and are not safe for refactoring
+   */
+  List<Source> get refactoringUnsafeSources;
+
+  /**
    * Return a fully resolved AST for a single compilation unit within the given library, or
    * `null` if the resolved AST is not already computed.
    *
@@ -503,13 +514,12 @@
 
   /**
    * Perform the next unit of work required to keep the analysis results up-to-date and return
-   * information about the consequent changes to the analysis results. If there were no results the
-   * returned array will be empty. If there are no more units of work required, then this method
-   * returns `null`. This method can be long running.
+   * information about the consequent changes to the analysis results. This method can be long
+   * running.
    *
-   * @return an array containing notices of changes to the analysis results
+   * @return the results of performing the analysis
    */
-  List<ChangeNotice> performAnalysisTask();
+  AnalysisResult performAnalysisTask();
 
   /**
    * Parse and resolve a single source within the given context to produce a fully resolved AST.
@@ -570,6 +580,19 @@
 
   /**
    * Set the contents of the given source to the given contents and mark the source as having
+   * changed. The additional offset and length information is used by the context to determine what
+   * reanalysis is necessary.
+   *
+   * @param source the source whose contents are being overridden
+   * @param contents the text to replace the range in the current contents
+   * @param offset the offset into the current contents
+   * @param oldLength the number of characters in the original contents that were replaced
+   * @param newLength the number of characters in the replacement text
+   */
+  void setChangedContents(Source source, String contents, int offset, int oldLength, int newLength);
+
+  /**
+   * Set the contents of the given source to the given contents and mark the source as having
    * changed. This has the effect of overriding the default contents of the source. If the contents
    * are `null` the override is removed so that the default contents will be returned.
    *
@@ -660,6 +683,13 @@
 abstract class AnalysisOptions {
 
   /**
+   * Return the maximum number of sources for which AST structures should be kept in the cache.
+   *
+   * @return the maximum number of sources for which AST structures should be kept in the cache
+   */
+  int get cacheSize;
+
+  /**
    * Return `true` if analysis is to generate dart2js related hint results.
    *
    * @return `true` if analysis is to generate dart2js related hint results
@@ -683,6 +713,47 @@
   bool get strictMode;
 }
 /**
+ * Instances of the class `AnalysisResult`
+ */
+class AnalysisResult {
+
+  /**
+   * The change notices associated with this result, or `null` if there were no changes and
+   * there is no more work to be done.
+   */
+  List<ChangeNotice> changeNotices;
+
+  /**
+   * The number of milliseconds required to determine which task was to be performed.
+   */
+  int getTime = 0;
+
+  /**
+   * The name of the class of the task that was performed.
+   */
+  String taskClassName;
+
+  /**
+   * The number of milliseconds required to perform the task.
+   */
+  int performTime = 0;
+
+  /**
+   * Initialize a newly created analysis result to have the given values.
+   *
+   * @param notices the change notices associated with this result
+   * @param getTime the number of milliseconds required to determine which task was to be performed
+   * @param taskClassName the name of the class of the task that was performed
+   * @param performTime the number of milliseconds required to perform the task
+   */
+  AnalysisResult(List<ChangeNotice> notices, int getTime, String taskClassName, int performTime) {
+    this.changeNotices = notices;
+    this.getTime = getTime;
+    this.taskClassName = taskClassName;
+    this.performTime = performTime;
+  }
+}
+/**
  * The interface `ChangeNotice` defines the behavior of objects that represent a change to the
  * analysis results associated with a given source.
  *
@@ -848,6 +919,11 @@
   int _maxCacheSize = 0;
 
   /**
+   * The policy used to determine which pieces of data to remove from the cache.
+   */
+  CacheRetentionPolicy _retentionPolicy;
+
+  /**
    * A list containing the most recently accessed sources with the most recently used at the end of
    * the list. When more sources are added than the maximum allowed then the least recently used
    * source will be removed and will have it's cached AST structure flushed.
@@ -855,25 +931,17 @@
   List<Source> _recentlyUsed;
 
   /**
-   * An array containing sources for which data should not be flushed.
-   */
-  List<Source> _priorityOrder = Source.EMPTY_ARRAY;
-
-  /**
-   * The number of times that the flushing of information from the cache has been disabled without
-   * being re-enabled.
-   */
-  int _cacheRemovalCount = 0;
-
-  /**
    * Initialize a newly created cache to maintain at most the given number of AST structures in the
    * cache.
    *
    * @param maxCacheSize the maximum number of sources for which AST structures should be kept in
    *          the cache
+   * @param retentionPolicy the policy used to determine which pieces of data to remove from the
+   *          cache
    */
-  AnalysisCache(int maxCacheSize) {
+  AnalysisCache(int maxCacheSize, CacheRetentionPolicy retentionPolicy) {
     this._maxCacheSize = maxCacheSize;
+    this._retentionPolicy = retentionPolicy;
     _recentlyUsed = new List<Source>();
   }
 
@@ -887,32 +955,12 @@
       _recentlyUsed.add(source);
       return;
     }
-    if (_cacheRemovalCount == 0 && _recentlyUsed.length >= _maxCacheSize) {
-      flushAstFromCache();
-    }
-    _recentlyUsed.add(source);
-  }
-
-  /**
-   * Disable flushing information from the cache until [enableCacheRemoval] has been
-   * called.
-   */
-  void disableCacheRemoval() {
-    _cacheRemovalCount++;
-  }
-
-  /**
-   * Re-enable flushing information from the cache.
-   */
-  void enableCacheRemoval() {
-    if (_cacheRemovalCount > 0) {
-      _cacheRemovalCount--;
-    }
-    if (_cacheRemovalCount == 0) {
-      while (_recentlyUsed.length > _maxCacheSize) {
-        flushAstFromCache();
+    while (_recentlyUsed.length >= _maxCacheSize) {
+      if (!flushAstFromCache()) {
+        break;
       }
     }
+    _recentlyUsed.add(source);
   }
 
   /**
@@ -932,13 +980,6 @@
   SourceEntry get(Source source) => _sourceMap[source];
 
   /**
-   * Return an array containing sources for which data should not be flushed.
-   *
-   * @return an array containing sources for which data should not be flushed
-   */
-  List<Source> get priorityOrder => _priorityOrder;
-
-  /**
    * Associate the given entry with the given source.
    *
    * @param source the source with which the entry is to be associated
@@ -958,19 +999,36 @@
   }
 
   /**
-   * Set the sources for which data should not be flushed to the given array.
+   * Set the maximum size of the cache to the given size.
    *
-   * @param sources the sources for which data should not be flushed
+   * @param size the maximum number of sources for which AST structures should be kept in the cache
    */
-  void set priorityOrder(List<Source> sources) {
-    _priorityOrder = sources;
+  void set maxCacheSize(int size) {
+    _maxCacheSize = size;
+    while (_recentlyUsed.length > _maxCacheSize) {
+      if (!flushAstFromCache()) {
+        break;
+      }
+    }
   }
 
   /**
-   * Flush one AST structure from the cache.
+   * Return the number of sources that are mapped to cache entries.
+   *
+   * @return the number of sources that are mapped to cache entries
    */
-  void flushAstFromCache() {
+  int size() => _sourceMap.length;
+
+  /**
+   * Attempt to flush one AST structure from the cache.
+   *
+   * @return `true` if a structure was flushed
+   */
+  bool flushAstFromCache() {
     Source removedSource = removeAstToFlush();
+    if (removedSource == null) {
+      return false;
+    }
     SourceEntry sourceEntry = _sourceMap[removedSource];
     if (sourceEntry is HtmlEntry) {
       HtmlEntryImpl htmlCopy = ((sourceEntry as HtmlEntry)).writableCopy;
@@ -981,20 +1039,7 @@
       dartCopy.flushAstStructures();
       _sourceMap[removedSource] = dartCopy;
     }
-  }
-
-  /**
-   * Return `true` if the given source is in the array of priority sources.
-   *
-   * @return `true` if the given source is in the array of priority sources
-   */
-  bool isPrioritySource(Source source) {
-    for (Source prioritySource in _priorityOrder) {
-      if (source == prioritySource) {
-        return true;
-      }
-    }
-    return false;
+    return true;
   }
 
   /**
@@ -1005,17 +1050,39 @@
    * @return the source that was removed
    */
   Source removeAstToFlush() {
+    int sourceToRemove = -1;
     for (int i = 0; i < _recentlyUsed.length; i++) {
       Source source = _recentlyUsed[i];
-      if (!isPrioritySource(source)) {
+      RetentionPriority priority = _retentionPolicy.getAstPriority(source, _sourceMap[source]);
+      if (identical(priority, RetentionPriority.LOW)) {
         return _recentlyUsed.removeAt(i);
+      } else if (identical(priority, RetentionPriority.MEDIUM) && sourceToRemove < 0) {
+        sourceToRemove = i;
       }
     }
-    AnalysisEngine.instance.logger.logError2("Internal error: The number of priority sources (${_priorityOrder.length}) is greater than the maximum cache size (${_maxCacheSize})", new JavaException());
-    return _recentlyUsed.removeAt(0);
+    if (sourceToRemove < 0) {
+      AnalysisEngine.instance.logger.logError2("Internal error: Could not flush data from the cache", new JavaException());
+      return null;
+    }
+    return _recentlyUsed.removeAt(sourceToRemove);
   }
 }
 /**
+ * Instances of the class `CacheRetentionPolicy` define the behavior of objects that determine
+ * how important it is for data to be retained in the analysis cache.
+ */
+abstract class CacheRetentionPolicy {
+
+  /**
+   * Return the priority of retaining the AST structure for the given source.
+   *
+   * @param source the source whose AST structure is being considered for removal
+   * @param sourceEntry the entry representing the source
+   * @return the priority of retaining the AST structure for the given source
+   */
+  RetentionPriority getAstPriority(Source source, SourceEntry sourceEntry);
+}
+/**
  * The enumeration `CacheState` defines the possible states of cached data.
  */
 class CacheState extends Enum<CacheState> {
@@ -1208,6 +1275,21 @@
    */
   Object getValue2(DataDescriptor descriptor, Source librarySource);
   DartEntryImpl get writableCopy;
+
+  /**
+   * Return `true` if the data represented by the given descriptor is marked as being invalid.
+   * If the descriptor represents library-specific data then this method will return `true` if
+   * the data associated with any library it marked as invalid.
+   *
+   * @param descriptor the descriptor representing which data is being tested
+   * @return `true` if the data is marked as being invalid
+   */
+  bool hasInvalidData(DataDescriptor descriptor);
+
+  /**
+   * Return `true` if this data is safe to use in refactoring.
+   */
+  bool get isRefactoringSafe;
 }
 /**
  * Instances of the class `DartEntryImpl` implement a [DartEntry].
@@ -1530,6 +1612,45 @@
     copy.copyFrom(this);
     return copy;
   }
+  bool hasInvalidData(DataDescriptor descriptor) {
+    if (identical(descriptor, DartEntry.ELEMENT)) {
+      return identical(_elementState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.EXPORTED_LIBRARIES)) {
+      return identical(_exportedLibrariesState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.IMPORTED_LIBRARIES)) {
+      return identical(_importedLibrariesState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.INCLUDED_PARTS)) {
+      return identical(_includedPartsState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.IS_CLIENT)) {
+      return identical(_clientServerState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.IS_LAUNCHABLE)) {
+      return identical(_launchableState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.PARSE_ERRORS)) {
+      return identical(_parseErrorsState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.PARSED_UNIT)) {
+      return identical(_parsedUnitState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
+      return identical(_publicNamespaceState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
+      return identical(_sourceKindState, CacheState.INVALID);
+    } else if (identical(descriptor, DartEntry.RESOLUTION_ERRORS) || identical(descriptor, DartEntry.RESOLVED_UNIT) || identical(descriptor, DartEntry.VERIFICATION_ERRORS) || identical(descriptor, DartEntry.HINTS)) {
+      DartEntryImpl_ResolutionState state = _resolutionState;
+      while (state != null) {
+        if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
+          return identical(state._resolutionErrorsState, CacheState.INVALID);
+        } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
+          return identical(state._resolvedUnitState, CacheState.INVALID);
+        } else if (identical(descriptor, DartEntry.VERIFICATION_ERRORS)) {
+          return identical(state._verificationErrorsState, CacheState.INVALID);
+        } else if (identical(descriptor, DartEntry.HINTS)) {
+          return identical(state._hintsState, CacheState.INVALID);
+        }
+      }
+      return false;
+    } else {
+      return identical(super.getState(descriptor), CacheState.INVALID);
+    }
+  }
 
   /**
    * Invalidate all of the information associated with the compilation unit.
@@ -1565,6 +1686,17 @@
     _publicNamespaceState = CacheState.INVALID;
     _resolutionState.invalidateAllResolutionInformation();
   }
+  bool get isRefactoringSafe {
+    DartEntryImpl_ResolutionState state = _resolutionState;
+    while (state != null) {
+      CacheState resolvedState = state._resolvedUnitState;
+      if (resolvedState != CacheState.VALID && resolvedState != CacheState.FLUSHED) {
+        return false;
+      }
+      state = state._nextState;
+    }
+    return true;
+  }
 
   /**
    * Record that an error occurred while attempting to scan or parse the entry represented by this
@@ -2077,8 +2209,6 @@
    * will not change the state of any parse results.
    */
   void recordResolutionError() {
-    _nextState = null;
-    _librarySource = null;
     _resolvedUnitState = CacheState.ERROR;
     _resolvedUnit = null;
     _resolutionErrorsState = CacheState.ERROR;
@@ -2087,6 +2217,9 @@
     _verificationErrors = AnalysisError.NO_ERRORS;
     _hintsState = CacheState.ERROR;
     _hints = AnalysisError.NO_ERRORS;
+    if (_nextState != null) {
+      _nextState.recordResolutionError();
+    }
   }
 
   /**
@@ -2402,6 +2535,33 @@
   }
 }
 /**
+ * The enumerated type `RetentionPriority` represents the priority of data in the cache in
+ * terms of the desirability of retaining some specified data about a specified source.
+ */
+class RetentionPriority extends Enum<RetentionPriority> {
+
+  /**
+   * A priority indicating that a given piece of data can be removed from the cache without
+   * reservation.
+   */
+  static final RetentionPriority LOW = new RetentionPriority('LOW', 0);
+
+  /**
+   * A priority indicating that a given piece of data should not be removed from the cache unless
+   * there are no sources for which the corresponding data has a lower priority. Currently used for
+   * data that is needed in order to finish some outstanding analysis task.
+   */
+  static final RetentionPriority MEDIUM = new RetentionPriority('MEDIUM', 1);
+
+  /**
+   * A priority indicating that a given piece of data should not be removed from the cache.
+   * Currently used for data related to a priority source.
+   */
+  static final RetentionPriority HIGH = new RetentionPriority('HIGH', 2);
+  static final List<RetentionPriority> values = [LOW, MEDIUM, HIGH];
+  RetentionPriority(String name, int ordinal) : super(name, ordinal);
+}
+/**
  * The interface `SourceEntry` defines the behavior of objects that maintain the information
  * cached by an analysis context about an individual source, no matter what kind of source it is.
  *
@@ -2692,9 +2852,17 @@
 class AnalysisContextImpl implements InternalAnalysisContext {
 
   /**
+   * The difference between the maximum cache size and the maximum priority order size. The priority
+   * list must be capped so that it is less than the cache size. Failure to do so can result in an
+   * infinite loop in performAnalysisTask() because re-caching one AST structure can cause another
+   * priority source's AST structure to be flushed.
+   */
+  static int _PRIORITY_ORDER_SIZE_DELTA = 4;
+
+  /**
    * The set of analysis options controlling the behavior of this context.
    */
-  AnalysisOptions _options = new AnalysisOptionsImpl();
+  AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
 
   /**
    * The source factory used to create the sources that can be analyzed in this context.
@@ -2704,7 +2872,12 @@
   /**
    * A table mapping the sources known to the context to the information known about the source.
    */
-  AnalysisCache _cache = new AnalysisCache(_MAX_CACHE_SIZE);
+  AnalysisCache _cache;
+
+  /**
+   * An array containing sources for which data should not be flushed.
+   */
+  List<Source> _priorityOrder = Source.EMPTY_ARRAY;
 
   /**
    * A table mapping sources to the change notices that are waiting to be returned related to that
@@ -2730,23 +2903,11 @@
   AnalysisContextImpl_AnalysisTaskResultRecorder _resultRecorder;
 
   /**
-   * The maximum number of sources for which data should be kept in the cache.
-   */
-  static int _MAX_CACHE_SIZE = 64;
-
-  /**
-   * The maximum number of sources that can be on the priority list. This <b>must</b> be less than
-   * the [MAX_CACHE_SIZE] in order to prevent an infinite loop in performAnalysisTask().
-   *
-   * @see #setAnalysisPriorityOrder(List)
-   */
-  static int _MAX_PRIORITY_LIST_SIZE = _MAX_CACHE_SIZE - 4;
-
-  /**
    * Initialize a newly created analysis context.
    */
   AnalysisContextImpl() : super() {
     _resultRecorder = new AnalysisContextImpl_AnalysisTaskResultRecorder(this);
+    _cache = new AnalysisCache(AnalysisOptionsImpl.DEFAULT_CACHE_SIZE, new AnalysisContextImpl_ContextRetentionPolicy(this));
   }
   void addSourceInfo(Source source, SourceEntry info) {
     _cache.put(source, info);
@@ -2819,7 +2980,7 @@
     return null;
   }
   List<AnalysisError> computeErrors(Source source) {
-    bool enableHints = analysisOptions.hint;
+    bool enableHints = _options.hint;
     SourceEntry sourceEntry = getReadableSourceEntry(source);
     if (sourceEntry is DartEntry) {
       List<AnalysisError> errors = new List<AnalysisError>();
@@ -2886,7 +3047,12 @@
           throw new AnalysisException.con1("computeResolvableCompilationUnit for non-Dart: ${source.fullName}");
         }
         if (identical(dartEntry.getState(DartEntry.PARSED_UNIT), CacheState.ERROR)) {
-          throw new AnalysisException.con1("Internal error: computeResolvableCompilationUnit could not parse ${source.fullName}");
+          AnalysisException cause = dartEntry.exception;
+          if (cause == null) {
+            throw new AnalysisException.con1("Internal error: computeResolvableCompilationUnit could not parse ${source.fullName}");
+          } else {
+            throw new AnalysisException.con2("Internal error: computeResolvableCompilationUnit could not parse ${source.fullName}", cause);
+          }
         }
         DartEntryImpl dartCopy = dartEntry.writableCopy;
         CompilationUnit unit = dartCopy.resolvableCompilationUnit;
@@ -3133,6 +3299,20 @@
     }
     return namespace;
   }
+  List<Source> get refactoringUnsafeSources {
+    List<Source> sources = new List<Source>();
+    {
+      for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
+        SourceEntry sourceEntry = entry.getValue();
+        if (sourceEntry is DartEntry) {
+          if (!((sourceEntry as DartEntry)).isRefactoringSafe) {
+            sources.add(entry.getKey());
+          }
+        }
+      }
+    }
+    return new List.from(sources);
+  }
   CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
     if (library == null) {
       return null;
@@ -3158,8 +3338,8 @@
   List<Source> get sourcesNeedingProcessing {
     Set<Source> sources = new Set<Source>();
     {
-      bool hintsEnabled = analysisOptions.hint;
-      for (Source source in _cache.priorityOrder) {
+      bool hintsEnabled = _options.hint;
+      for (Source source in _priorityOrder) {
         getSourcesNeedingProcessing2(source, _cache.get(source), true, hintsEnabled, sources);
       }
       for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
@@ -3246,11 +3426,14 @@
   }
   CompilationUnit parseCompilationUnit(Source source) => getDartParseData2(source, DartEntry.PARSED_UNIT, null);
   HtmlUnit parseHtmlUnit(Source source) => getHtmlParseData(source, HtmlEntry.PARSED_UNIT, null);
-  List<ChangeNotice> performAnalysisTask() {
+  AnalysisResult performAnalysisTask() {
+    int getStart = JavaSystem.currentTimeMillis();
     AnalysisTask task = nextTaskAnalysisTask;
+    int getEnd = JavaSystem.currentTimeMillis();
     if (task == null) {
-      return getChangeNotices(true);
+      return new AnalysisResult(getChangeNotices(true), getEnd - getStart, null, -1);
     }
+    int performStart = JavaSystem.currentTimeMillis();
     try {
       task.perform(_resultRecorder);
     } on AnalysisException catch (exception) {
@@ -3258,7 +3441,8 @@
         AnalysisEngine.instance.logger.logError2("Internal error while performing the task: ${task}", exception);
       }
     }
-    return getChangeNotices(false);
+    int performEnd = JavaSystem.currentTimeMillis();
+    return new AnalysisResult(getChangeNotices(false), getEnd - getStart, task.runtimeType.toString(), performEnd - performStart);
   }
   void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
     {
@@ -3285,26 +3469,48 @@
   HtmlUnit resolveHtmlUnit(Source htmlSource) => parseHtmlUnit(htmlSource);
   void set analysisOptions(AnalysisOptions options) {
     {
-      this._options = options;
-      invalidateAllResolutionInformation();
+      bool needsRecompute = this._options.dart2jsHint != options.dart2jsHint || (this._options.hint && !options.hint);
+      int cacheSize = options.cacheSize;
+      if (this._options.cacheSize != cacheSize) {
+        this._options.cacheSize = cacheSize;
+        _cache.maxCacheSize = cacheSize;
+        int maxPriorityOrderSize = cacheSize - _PRIORITY_ORDER_SIZE_DELTA;
+        if (_priorityOrder.length > maxPriorityOrderSize) {
+          List<Source> newPriorityOrder = new List<Source>(maxPriorityOrderSize);
+          JavaSystem.arraycopy(_priorityOrder, 0, newPriorityOrder, 0, maxPriorityOrderSize);
+          _priorityOrder = newPriorityOrder;
+        }
+      }
+      this._options.dart2jsHint = options.dart2jsHint;
+      this._options.hint = options.hint;
+      this._options.strictMode = options.strictMode;
+      if (needsRecompute) {
+        invalidateAllResolutionInformation();
+      }
     }
   }
   void set analysisPriorityOrder(List<Source> sources) {
     {
       if (sources == null || sources.isEmpty) {
-        _cache.priorityOrder = Source.EMPTY_ARRAY;
+        _priorityOrder = Source.EMPTY_ARRAY;
       } else {
         while (sources.remove(null)) {
         }
         if (sources.isEmpty) {
-          _cache.priorityOrder = Source.EMPTY_ARRAY;
+          _priorityOrder = Source.EMPTY_ARRAY;
         }
-        int count = Math.min(sources.length, _MAX_PRIORITY_LIST_SIZE);
-        List<Source> priorityOrder = new List<Source>(count);
+        int count = Math.min(sources.length, _options.cacheSize - _PRIORITY_ORDER_SIZE_DELTA);
+        _priorityOrder = new List<Source>(count);
         for (int i = 0; i < count; i++) {
-          priorityOrder[i] = sources[i];
+          _priorityOrder[i] = sources[i];
         }
-        _cache.priorityOrder = priorityOrder;
+      }
+    }
+  }
+  void setChangedContents(Source source, String contents, int offset, int oldLength, int newLength) {
+    {
+      if (_sourceFactory.setContents(source, contents)) {
+        sourceChanged(source);
       }
     }
   }
@@ -3792,8 +3998,8 @@
    */
   AnalysisTask get nextTaskAnalysisTask {
     {
-      bool hintsEnabled = analysisOptions.hint;
-      for (Source source in _cache.priorityOrder) {
+      bool hintsEnabled = _options.hint;
+      for (Source source in _priorityOrder) {
         AnalysisTask task = getNextTaskAnalysisTask2(source, _cache.get(source), true, hintsEnabled);
         if (task != null) {
           return task;
@@ -3832,7 +4038,7 @@
         _cache.put(source, dartCopy);
         return new ParseDartTask(this, source);
       }
-      if (isPriority) {
+      if (isPriority && parseErrorsState != CacheState.ERROR) {
         CompilationUnit parseUnit = dartEntry.anyParsedCompilationUnit;
         if (parseUnit == null) {
           DartEntryImpl dartCopy = dartEntry.writableCopy;
@@ -3853,13 +4059,10 @@
           }
           CacheState resolvedUnitState = dartEntry.getState2(DartEntry.RESOLVED_UNIT, librarySource);
           if (identical(resolvedUnitState, CacheState.INVALID) || (isPriority && identical(resolvedUnitState, CacheState.FLUSHED))) {
-            LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
-            if (libraryElement != null) {
-              DartEntryImpl dartCopy = dartEntry.writableCopy;
-              dartCopy.setState2(DartEntry.RESOLVED_UNIT, librarySource, CacheState.IN_PROCESS);
-              _cache.put(source, dartCopy);
-              return new ResolveDartUnitTask(this, source, libraryElement);
-            }
+            DartEntryImpl dartCopy = dartEntry.writableCopy;
+            dartCopy.setState2(DartEntry.RESOLVED_UNIT, librarySource, CacheState.IN_PROCESS);
+            _cache.put(source, dartCopy);
+            return new ResolveDartLibraryTask(this, source, librarySource);
           }
           CacheState verificationErrorsState = dartEntry.getState2(DartEntry.VERIFICATION_ERRORS, librarySource);
           if (identical(verificationErrorsState, CacheState.INVALID) || (isPriority && identical(verificationErrorsState, CacheState.FLUSHED))) {
@@ -4502,8 +4705,7 @@
             for (Source source in library.compilationUnitSources) {
               CompilationUnit unit = library.getAST(source);
               List<AnalysisError> errors = errorListener.getErrors2(source);
-              unit.resolutionErrors = errors;
-              LineInfo lineInfo = unit.lineInfo;
+              LineInfo lineInfo = getLineInfo(source);
               DartEntry dartEntry = _cache.get(source) as DartEntry;
               int sourceTime = source.modificationStamp;
               if (dartEntry.modificationTime != sourceTime) {
@@ -4780,6 +4982,25 @@
   SourceEntry visitResolveDartUnitTask(ResolveDartUnitTask task) => AnalysisContextImpl_this.recordResolveDartUnitTaskResults(task);
   SourceEntry visitResolveHtmlTask(ResolveHtmlTask task) => AnalysisContextImpl_this.recordResolveHtmlTaskResults(task);
 }
+class AnalysisContextImpl_ContextRetentionPolicy implements CacheRetentionPolicy {
+  final AnalysisContextImpl AnalysisContextImpl_this;
+  AnalysisContextImpl_ContextRetentionPolicy(this.AnalysisContextImpl_this);
+  RetentionPriority getAstPriority(Source source, SourceEntry sourceEntry) {
+    for (Source prioritySource in AnalysisContextImpl_this._priorityOrder) {
+      if (source == prioritySource) {
+        return RetentionPriority.HIGH;
+      }
+    }
+    if (sourceEntry is DartEntry) {
+      DartEntry dartEntry = sourceEntry as DartEntry;
+      if (astIsNeeded(dartEntry)) {
+        return RetentionPriority.MEDIUM;
+      }
+    }
+    return RetentionPriority.LOW;
+  }
+  bool astIsNeeded(DartEntry dartEntry) => dartEntry.hasInvalidData(DartEntry.HINTS) || dartEntry.hasInvalidData(DartEntry.VERIFICATION_ERRORS) || dartEntry.hasInvalidData(DartEntry.RESOLUTION_ERRORS);
+}
 /**
  * Instances of the class `AnalysisErrorInfoImpl` represent the analysis errors and line info
  * associated with a source.
@@ -4829,10 +5050,19 @@
 class AnalysisOptionsImpl implements AnalysisOptions {
 
   /**
-   * A flag indicating whether analysis is to use strict mode. In strict mode, error reporting is
-   * based exclusively on the static type information.
+   * The maximum number of sources for which data should be kept in the cache.
    */
-  bool _strictMode = true;
+  static int DEFAULT_CACHE_SIZE = 64;
+
+  /**
+   * The maximum number of sources for which AST structures should be kept in the cache.
+   */
+  int _cacheSize = DEFAULT_CACHE_SIZE;
+
+  /**
+   * A flag indicating whether analysis is to generate dart2js related hint results.
+   */
+  bool _dart2jsHint = true;
 
   /**
    * A flag indicating whether analysis is to generate hint results (e.g. type inference based
@@ -4841,9 +5071,29 @@
   bool _hint = true;
 
   /**
-   * A flag indicating whether analysis is to generate dart2js related hint results.
+   * A flag indicating whether analysis is to use strict mode. In strict mode, error reporting is
+   * based exclusively on the static type information.
    */
-  bool _dart2jsHint = true;
+  bool _strictMode = true;
+
+  /**
+   * Initialize a newly created set of analysis options to have their default values.
+   */
+  AnalysisOptionsImpl();
+
+  /**
+   * Initialize a newly created set of analysis options to have the same values as those in the
+   * given set of analysis options.
+   *
+   * @param options the analysis options whose values are being copied
+   */
+  AnalysisOptionsImpl.con1(AnalysisOptions options) {
+    _cacheSize = options.cacheSize;
+    _dart2jsHint = options.dart2jsHint;
+    _hint = options.hint;
+    _strictMode = options.strictMode;
+  }
+  int get cacheSize => _cacheSize;
   bool get dart2jsHint => _dart2jsHint;
   bool get hint => _hint;
 
@@ -4856,6 +5106,17 @@
   bool get strictMode => _strictMode;
 
   /**
+   * Set the maximum number of sources for which AST structures should be kept in the cache to the
+   * given size.
+   *
+   * @param cacheSize the maximum number of sources for which AST structures should be kept in the
+   *          cache
+   */
+  void set cacheSize(int cacheSize) {
+    this._cacheSize = cacheSize;
+  }
+
+  /**
    * Set whether analysis is to generate dart2js related hint results.
    *
    * @param hint `true` if analysis is to generate dart2js related hint results
@@ -5207,6 +5468,13 @@
       return super.resolveHtmlUnit(unitSource);
     }
   }
+  void setChangedContents(Source source, String contents, int offset, int oldLength, int newLength) {
+    if (source.isInSystemLibrary) {
+      _sdkAnalysisContext.setChangedContents(source, contents, offset, oldLength, newLength);
+    } else {
+      super.setChangedContents(source, contents, offset, oldLength, newLength);
+    }
+  }
   void setContents(Source source, String contents) {
     if (source.isInSystemLibrary) {
       _sdkAnalysisContext.setContents(source, contents);
@@ -5541,6 +5809,7 @@
   }
   Namespace getPublicNamespace(LibraryElement library) => basis.getPublicNamespace(library);
   Namespace getPublicNamespace2(Source source) => basis.getPublicNamespace2(source);
+  List<Source> get refactoringUnsafeSources => basis.refactoringUnsafeSources;
   CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
     InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-getResolvedCompilationUnit");
     try {
@@ -5624,15 +5893,15 @@
       instrumentation.log();
     }
   }
-  List<ChangeNotice> performAnalysisTask() {
+  AnalysisResult performAnalysisTask() {
     InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-performAnalysisTask");
     try {
       instrumentation.metric3("contextId", _contextId);
-      List<ChangeNotice> ret = basis.performAnalysisTask();
-      if (ret != null) {
-        instrumentation.metric2("ChangeNotice-count", ret.length);
+      AnalysisResult result = basis.performAnalysisTask();
+      if (result.changeNotices != null) {
+        instrumentation.metric2("ChangeNotice-count", result.changeNotices.length);
       }
-      return ret;
+      return result;
     } finally {
       instrumentation.log2(2);
     }
@@ -5694,6 +5963,15 @@
       instrumentation.log();
     }
   }
+  void setChangedContents(Source source, String contents, int offset, int oldLength, int newLength) {
+    InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setChangedContents");
+    try {
+      instrumentation.metric3("contextId", _contextId);
+      basis.setChangedContents(source, contents, offset, oldLength, newLength);
+    } finally {
+      instrumentation.log();
+    }
+  }
   void setContents(Source source, String contents) {
     InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis-setContents");
     try {
@@ -6276,10 +6554,10 @@
   accept(AnalysisTaskVisitor visitor) => visitor.visitGenerateDartErrorsTask(this);
   String get taskDescription => "generate errors and warnings for ${source.fullName}";
   void internalPerform() {
+    InternalAnalysisContext context = this.context;
+    TimestampedData<CompilationUnit> data = context.internalResolveCompilationUnit(source, libraryElement);
     TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.errors.start();
     try {
-      InternalAnalysisContext context = this.context;
-      TimestampedData<CompilationUnit> data = context.internalResolveCompilationUnit(source, libraryElement);
       modificationTime = data.modificationTime;
       CompilationUnit unit = data.data;
       RecordingErrorListener errorListener = new RecordingErrorListener();
@@ -6339,12 +6617,20 @@
     Source unitSource = libraryElement.definingCompilationUnit.source;
     TimestampedData<CompilationUnit> resolvedUnit = getCompilationUnit(unitSource);
     timestampMap[unitSource] = resolvedUnit;
-    compilationUnits[0] = resolvedUnit.data;
+    CompilationUnit unit = resolvedUnit.data;
+    if (unit == null) {
+      throw new AnalysisException.con1("Internal error: GenerateDartHintsTask failed to access resolved compilation unit for ${unitSource.fullName}");
+    }
+    compilationUnits[0] = unit;
     for (int i = 0; i < partCount; i++) {
       unitSource = parts[i].source;
       resolvedUnit = getCompilationUnit(unitSource);
       timestampMap[unitSource] = resolvedUnit;
-      compilationUnits[i + 1] = resolvedUnit.data;
+      unit = resolvedUnit.data;
+      if (unit == null) {
+        throw new AnalysisException.con1("Internal error: GenerateDartHintsTask failed to access resolved compilation unit for ${unitSource.fullName}");
+      }
+      compilationUnits[i + 1] = unit;
     }
     HintGenerator hintGenerator = new HintGenerator(compilationUnits, context, errorListener);
     hintGenerator.generateForLibrary();
@@ -6354,7 +6640,6 @@
       TimestampedData<CompilationUnit> unitData = entry.getValue();
       List<AnalysisError> errors = errorListener.getErrors2(source);
       hintMap[source] = new TimestampedData<List<AnalysisError>>(unitData.modificationTime, errors);
-      unitData.data.hints = errors;
     }
   }
 
@@ -6520,7 +6805,6 @@
           _hasPartOfDirective2 = true;
         }
       }
-      compilationUnit.parsingErrors = errors;
       compilationUnit.lineInfo = lineInfo;
     } finally {
       timeCounterParse.stop();
@@ -6840,7 +7124,6 @@
     } finally {
       counterHandleErrors.stop();
     }
-    unit.resolutionErrors = errorListener.errors;
     resolvedUnit = unit;
   }
 
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart
index 27b527c..98fb095 100644
--- a/pkg/analyzer_experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -807,17 +807,29 @@
   static final CompileTimeErrorCode CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD = new CompileTimeErrorCode.con1('CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD', 11, "'%s' cannot be used to name a constructor and a method in this class");
 
   /**
+   * 7. Classes: It is a compile time error if a generic class declares a type variable with the
+   * same name as the class or any of its members or constructors.
+   */
+  static final CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_CLASS = new CompileTimeErrorCode.con1('CONFLICTING_TYPE_VARIABLE_AND_CLASS', 12, "'%s' cannot be used to name a type varaible in a class with the same name");
+
+  /**
+   * 7. Classes: It is a compile time error if a generic class declares a type variable with the
+   * same name as the class or any of its members or constructors.
+   */
+  static final CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_MEMBER = new CompileTimeErrorCode.con1('CONFLICTING_TYPE_VARIABLE_AND_MEMBER', 13, "'%s' cannot be used to name a type varaible and member in this class");
+
+  /**
    * 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
    * uncaught exception being thrown.
    */
-  static final CompileTimeErrorCode CONST_CONSTRUCTOR_THROWS_EXCEPTION = new CompileTimeErrorCode.con1('CONST_CONSTRUCTOR_THROWS_EXCEPTION', 12, "'const' constructors cannot throw exceptions");
+  static final CompileTimeErrorCode CONST_CONSTRUCTOR_THROWS_EXCEPTION = new CompileTimeErrorCode.con1('CONST_CONSTRUCTOR_THROWS_EXCEPTION', 14, "'const' constructors cannot throw exceptions");
 
   /**
    * 7.6.3 Constant Constructors: The superinitializer that appears, explicitly or implicitly, in
    * the initializer list of a constant constructor must specify a constant constructor of the
    * superclass of the immediately enclosing class or a compile-time error occurs.
    */
-  static final CompileTimeErrorCode CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER = new CompileTimeErrorCode.con1('CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER', 13, "Constant constructor cannot call non-constant super constructor");
+  static final CompileTimeErrorCode CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER = new CompileTimeErrorCode.con1('CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER', 15, "Constant constructor cannot call non-constant super constructor");
 
   /**
    * 7.6.3 Constant Constructors: It is a compile-time error if a constant constructor is declared
@@ -825,7 +837,7 @@
    *
    * The above refers to both locally declared and inherited instance variables.
    */
-  static final CompileTimeErrorCode CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD = new CompileTimeErrorCode.con1('CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD', 14, "Cannot define the 'const' constructor for a class with non-final fields");
+  static final CompileTimeErrorCode CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD = new CompileTimeErrorCode.con1('CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD', 16, "Cannot define the 'const' constructor for a class with non-final fields");
 
   /**
    * 7.6.1 Generative Constructors: In checked mode, it is a dynamic type error if o is not
@@ -838,25 +850,32 @@
    * @param initializerType the name of the type of the initializer expression
    * @param fieldType the name of the type of the field
    */
-  static final CompileTimeErrorCode CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE', 15, "The initializer type '%s' cannot be assigned to the field type '%s'");
+  static final CompileTimeErrorCode CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE', 17, "The initializer type '%s' cannot be assigned to the field type '%s'");
 
   /**
    * 6.2 Formal Parameters: It is a compile-time error if a formal parameter is declared as a
    * constant variable.
    */
-  static final CompileTimeErrorCode CONST_FORMAL_PARAMETER = new CompileTimeErrorCode.con1('CONST_FORMAL_PARAMETER', 16, "Parameters cannot be 'const'");
+  static final CompileTimeErrorCode CONST_FORMAL_PARAMETER = new CompileTimeErrorCode.con1('CONST_FORMAL_PARAMETER', 18, "Parameters cannot be 'const'");
 
   /**
    * 5 Variables: A constant variable must be initialized to a compile-time constant or a
    * compile-time error occurs.
    */
-  static final CompileTimeErrorCode CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE = new CompileTimeErrorCode.con1('CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE', 17, "'const' variables must be constant value");
+  static final CompileTimeErrorCode CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE = new CompileTimeErrorCode.con1('CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE', 19, "'const' variables must be constant value");
 
   /**
    * 7.5 Instance Variables: It is a compile-time error if an instance variable is declared to be
    * constant.
    */
-  static final CompileTimeErrorCode CONST_INSTANCE_FIELD = new CompileTimeErrorCode.con1('CONST_INSTANCE_FIELD', 18, "Only static fields can be declared as 'const'");
+  static final CompileTimeErrorCode CONST_INSTANCE_FIELD = new CompileTimeErrorCode.con1('CONST_INSTANCE_FIELD', 20, "Only static fields can be declared as 'const'");
+
+  /**
+   * 12.8 Maps: It is a compile-time error if the key of an entry in a constant map literal is an
+   * instance of a class that implements the operator <i>==</i> unless the key is a string or
+   * integer.
+   */
+  static final CompileTimeErrorCode CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS = new CompileTimeErrorCode.con1('CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS', 21, "The constant map entry key expression type '%s' cannot override the == operator");
 
   /**
    * 5 Variables: A constant variable must be initialized to a compile-time constant (12.1) or a
@@ -864,45 +883,45 @@
    *
    * @param name the name of the uninitialized final variable
    */
-  static final CompileTimeErrorCode CONST_NOT_INITIALIZED = new CompileTimeErrorCode.con1('CONST_NOT_INITIALIZED', 19, "The const variable '%s' must be initialized");
+  static final CompileTimeErrorCode CONST_NOT_INITIALIZED = new CompileTimeErrorCode.con1('CONST_NOT_INITIALIZED', 22, "The const variable '%s' must be initialized");
 
   /**
    * 12.11.2 Const: An expression of one of the forms !e, e1 && e2 or e1 || e2, where e, e1 and e2
    * are constant expressions that evaluate to a boolean value.
    */
-  static final CompileTimeErrorCode CONST_EVAL_TYPE_BOOL = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_BOOL', 20, "An expression of type 'bool' was expected");
+  static final CompileTimeErrorCode CONST_EVAL_TYPE_BOOL = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_BOOL', 23, "An expression of type 'bool' was expected");
 
   /**
    * 12.11.2 Const: An expression of one of the forms e1 == e2 or e1 != e2 where e1 and e2 are
    * constant expressions that evaluate to a numeric, string or boolean value or to null.
    */
-  static final CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_NUM_STRING = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_BOOL_NUM_STRING', 21, "An expression of type 'bool', 'num', 'String' or 'null' was expected");
+  static final CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_NUM_STRING = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_BOOL_NUM_STRING', 24, "An expression of type 'bool', 'num', 'String' or 'null' was expected");
 
   /**
    * 12.11.2 Const: An expression of one of the forms ~e, e1 ^ e2, e1 & e2, e1 | e2, e1 >> e2 or e1
    * << e2, where e, e1 and e2 are constant expressions that evaluate to an integer value or to
    * null.
    */
-  static final CompileTimeErrorCode CONST_EVAL_TYPE_INT = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_INT', 22, "An expression of type 'int' was expected");
+  static final CompileTimeErrorCode CONST_EVAL_TYPE_INT = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_INT', 25, "An expression of type 'int' was expected");
 
   /**
    * 12.11.2 Const: An expression of one of the forms e, e1 + e2, e1 - e2, e1 * e2, e1 / e2, e1 ~/
    * e2, e1 > e2, e1 < e2, e1 >= e2, e1 <= e2 or e1 % e2, where e, e1 and e2 are constant
    * expressions that evaluate to a numeric value or to null..
    */
-  static final CompileTimeErrorCode CONST_EVAL_TYPE_NUM = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_NUM', 23, "An expression of type 'num' was expected");
+  static final CompileTimeErrorCode CONST_EVAL_TYPE_NUM = new CompileTimeErrorCode.con1('CONST_EVAL_TYPE_NUM', 26, "An expression of type 'num' was expected");
 
   /**
    * 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
    * uncaught exception being thrown.
    */
-  static final CompileTimeErrorCode CONST_EVAL_THROWS_EXCEPTION = new CompileTimeErrorCode.con1('CONST_EVAL_THROWS_EXCEPTION', 24, "Evaluation of this constant expression causes exception");
+  static final CompileTimeErrorCode CONST_EVAL_THROWS_EXCEPTION = new CompileTimeErrorCode.con1('CONST_EVAL_THROWS_EXCEPTION', 27, "Evaluation of this constant expression causes exception");
 
   /**
    * 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
    * uncaught exception being thrown.
    */
-  static final CompileTimeErrorCode CONST_EVAL_THROWS_IDBZE = new CompileTimeErrorCode.con1('CONST_EVAL_THROWS_IDBZE', 25, "Evaluation of this constant expression throws IntegerDivisionByZeroException");
+  static final CompileTimeErrorCode CONST_EVAL_THROWS_IDBZE = new CompileTimeErrorCode.con1('CONST_EVAL_THROWS_IDBZE', 28, "Evaluation of this constant expression throws IntegerDivisionByZeroException");
 
   /**
    * 12.11.2 Const: If <i>T</i> is a parameterized type <i>S&lt;U<sub>1</sub>, &hellip;,
@@ -915,7 +934,7 @@
    * @see CompileTimeErrorCode#NEW_WITH_INVALID_TYPE_PARAMETERS
    * @see StaticTypeWarningCode#WRONG_NUMBER_OF_TYPE_ARGUMENTS
    */
-  static final CompileTimeErrorCode CONST_WITH_INVALID_TYPE_PARAMETERS = new CompileTimeErrorCode.con1('CONST_WITH_INVALID_TYPE_PARAMETERS', 26, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
+  static final CompileTimeErrorCode CONST_WITH_INVALID_TYPE_PARAMETERS = new CompileTimeErrorCode.con1('CONST_WITH_INVALID_TYPE_PARAMETERS', 29, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
 
   /**
    * 12.11.2 Const: If <i>e</i> is of the form <i>const T(a<sub>1</sub>, &hellip;, a<sub>n</sub>,
@@ -923,13 +942,13 @@
    * compile-time error if the type <i>T</i> does not declare a constant constructor with the same
    * name as the declaration of <i>T</i>.
    */
-  static final CompileTimeErrorCode CONST_WITH_NON_CONST = new CompileTimeErrorCode.con1('CONST_WITH_NON_CONST', 27, "The constructor being called is not a 'const' constructor");
+  static final CompileTimeErrorCode CONST_WITH_NON_CONST = new CompileTimeErrorCode.con1('CONST_WITH_NON_CONST', 30, "The constructor being called is not a 'const' constructor");
 
   /**
    * 12.11.2 Const: In all of the above cases, it is a compile-time error if <i>a<sub>i</sub>, 1
    * &lt;= i &lt;= n + k</i>, is not a compile-time constant expression.
    */
-  static final CompileTimeErrorCode CONST_WITH_NON_CONSTANT_ARGUMENT = new CompileTimeErrorCode.con1('CONST_WITH_NON_CONSTANT_ARGUMENT', 28, "Arguments of a constant creation must be constant expressions");
+  static final CompileTimeErrorCode CONST_WITH_NON_CONSTANT_ARGUMENT = new CompileTimeErrorCode.con1('CONST_WITH_NON_CONSTANT_ARGUMENT', 31, "Arguments of a constant creation must be constant expressions");
 
   /**
    * 12.11.2 Const: It is a compile-time error if <i>T</i> is not a class accessible in the current
@@ -942,12 +961,12 @@
    *
    * @param name the name of the non-type element
    */
-  static final CompileTimeErrorCode CONST_WITH_NON_TYPE = new CompileTimeErrorCode.con1('CONST_WITH_NON_TYPE', 29, "The name '%s' is not a class");
+  static final CompileTimeErrorCode CONST_WITH_NON_TYPE = new CompileTimeErrorCode.con1('CONST_WITH_NON_TYPE', 32, "The name '%s' is not a class");
 
   /**
    * 12.11.2 Const: It is a compile-time error if <i>T</i> includes any type parameters.
    */
-  static final CompileTimeErrorCode CONST_WITH_TYPE_PARAMETERS = new CompileTimeErrorCode.con1('CONST_WITH_TYPE_PARAMETERS', 30, "The constant creation cannot use a type parameter");
+  static final CompileTimeErrorCode CONST_WITH_TYPE_PARAMETERS = new CompileTimeErrorCode.con1('CONST_WITH_TYPE_PARAMETERS', 33, "The constant creation cannot use a type parameter");
 
   /**
    * 12.11.2 Const: It is a compile-time error if <i>T.id</i> is not the name of a constant
@@ -956,7 +975,7 @@
    * @param typeName the name of the type
    * @param constructorName the name of the requested constant constructor
    */
-  static final CompileTimeErrorCode CONST_WITH_UNDEFINED_CONSTRUCTOR = new CompileTimeErrorCode.con1('CONST_WITH_UNDEFINED_CONSTRUCTOR', 31, "The class '%s' does not have a constant constructor '%s'");
+  static final CompileTimeErrorCode CONST_WITH_UNDEFINED_CONSTRUCTOR = new CompileTimeErrorCode.con1('CONST_WITH_UNDEFINED_CONSTRUCTOR', 34, "The class '%s' does not have a constant constructor '%s'");
 
   /**
    * 12.11.2 Const: It is a compile-time error if <i>T.id</i> is not the name of a constant
@@ -964,26 +983,26 @@
    *
    * @param typeName the name of the type
    */
-  static final CompileTimeErrorCode CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT = new CompileTimeErrorCode.con1('CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT', 32, "The class '%s' does not have a default constant constructor");
+  static final CompileTimeErrorCode CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT = new CompileTimeErrorCode.con1('CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT', 35, "The class '%s' does not have a default constant constructor");
 
   /**
    * 15.3.1 Typedef: It is a compile-time error if any default values are specified in the signature
    * of a function type alias.
    */
-  static final CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS = new CompileTimeErrorCode.con1('DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS', 33, "Default values aren't allowed in typedefs");
+  static final CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS = new CompileTimeErrorCode.con1('DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS', 36, "Default values aren't allowed in typedefs");
 
   /**
    * 6.2.1 Required Formals: By means of a function signature that names the parameter and describes
    * its type as a function type. It is a compile-time error if any default values are specified in
    * the signature of such a function type.
    */
-  static final CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER = new CompileTimeErrorCode.con1('DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER', 34, "Default values aren't allowed in function type parameters");
+  static final CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER = new CompileTimeErrorCode.con1('DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER', 37, "Default values aren't allowed in function type parameters");
 
   /**
    * 3.1 Scoping: It is a compile-time error if there is more than one entity with the same name
    * declared in the same scope.
    */
-  static final CompileTimeErrorCode DUPLICATE_CONSTRUCTOR_DEFAULT = new CompileTimeErrorCode.con1('DUPLICATE_CONSTRUCTOR_DEFAULT', 35, "The default constructor is already defined");
+  static final CompileTimeErrorCode DUPLICATE_CONSTRUCTOR_DEFAULT = new CompileTimeErrorCode.con1('DUPLICATE_CONSTRUCTOR_DEFAULT', 38, "The default constructor is already defined");
 
   /**
    * 3.1 Scoping: It is a compile-time error if there is more than one entity with the same name
@@ -991,7 +1010,7 @@
    *
    * @param duplicateName the name of the duplicate entity
    */
-  static final CompileTimeErrorCode DUPLICATE_CONSTRUCTOR_NAME = new CompileTimeErrorCode.con1('DUPLICATE_CONSTRUCTOR_NAME', 36, "The constructor with name '%s' is already defined");
+  static final CompileTimeErrorCode DUPLICATE_CONSTRUCTOR_NAME = new CompileTimeErrorCode.con1('DUPLICATE_CONSTRUCTOR_NAME', 39, "The constructor with name '%s' is already defined");
 
   /**
    * 3.1 Scoping: It is a compile-time error if there is more than one entity with the same name
@@ -1004,7 +1023,7 @@
    *
    * @param duplicateName the name of the duplicate entity
    */
-  static final CompileTimeErrorCode DUPLICATE_DEFINITION = new CompileTimeErrorCode.con1('DUPLICATE_DEFINITION', 37, "The name '%s' is already defined");
+  static final CompileTimeErrorCode DUPLICATE_DEFINITION = new CompileTimeErrorCode.con1('DUPLICATE_DEFINITION', 40, "The name '%s' is already defined");
 
   /**
    * 7. Classes: It is a compile-time error if a class has an instance member and a static member
@@ -1016,21 +1035,21 @@
    * @param name the name of the conflicting members
    * @see #DUPLICATE_DEFINITION
    */
-  static final CompileTimeErrorCode DUPLICATE_DEFINITION_INHERITANCE = new CompileTimeErrorCode.con1('DUPLICATE_DEFINITION_INHERITANCE', 38, "The name '%s' is already defined in '%s'");
+  static final CompileTimeErrorCode DUPLICATE_DEFINITION_INHERITANCE = new CompileTimeErrorCode.con1('DUPLICATE_DEFINITION_INHERITANCE', 41, "The name '%s' is already defined in '%s'");
 
   /**
    * 12.14.2 Binding Actuals to Formals: It is a compile-time error if <i>q<sub>i</sub> =
    * q<sub>j</sub></i> for any <i>i != j</i> [where <i>q<sub>i</sub></i> is the label for a named
    * argument].
    */
-  static final CompileTimeErrorCode DUPLICATE_NAMED_ARGUMENT = new CompileTimeErrorCode.con1('DUPLICATE_NAMED_ARGUMENT', 39, "The argument for the named parameter '%s' was already specified");
+  static final CompileTimeErrorCode DUPLICATE_NAMED_ARGUMENT = new CompileTimeErrorCode.con1('DUPLICATE_NAMED_ARGUMENT', 42, "The argument for the named parameter '%s' was already specified");
 
   /**
    * SDK implementation libraries can be exported only by other SDK libraries.
    *
    * @param uri the uri pointing to a library
    */
-  static final CompileTimeErrorCode EXPORT_INTERNAL_LIBRARY = new CompileTimeErrorCode.con1('EXPORT_INTERNAL_LIBRARY', 40, "The library '%s' is internal and cannot be exported");
+  static final CompileTimeErrorCode EXPORT_INTERNAL_LIBRARY = new CompileTimeErrorCode.con1('EXPORT_INTERNAL_LIBRARY', 43, "The library '%s' is internal and cannot be exported");
 
   /**
    * 14.2 Exports: It is a compile-time error if the compilation unit found at the specified URI is
@@ -1038,7 +1057,7 @@
    *
    * @param uri the uri pointing to a non-library declaration
    */
-  static final CompileTimeErrorCode EXPORT_OF_NON_LIBRARY = new CompileTimeErrorCode.con1('EXPORT_OF_NON_LIBRARY', 41, "The exported library '%s' must not have a part-of directive");
+  static final CompileTimeErrorCode EXPORT_OF_NON_LIBRARY = new CompileTimeErrorCode.con1('EXPORT_OF_NON_LIBRARY', 44, "The exported library '%s' must not have a part-of directive");
 
   /**
    * 7.9 Superclasses: It is a compile-time error if the extends clause of a class <i>C</i> includes
@@ -1046,7 +1065,7 @@
    *
    * @param typeName the name of the superclass that was not found
    */
-  static final CompileTimeErrorCode EXTENDS_NON_CLASS = new CompileTimeErrorCode.con1('EXTENDS_NON_CLASS', 42, "Classes can only extend other classes");
+  static final CompileTimeErrorCode EXTENDS_NON_CLASS = new CompileTimeErrorCode.con1('EXTENDS_NON_CLASS', 45, "Classes can only extend other classes");
 
   /**
    * 12.2 Null: It is a compile-time error for a class to attempt to extend or implement Null.
@@ -1065,7 +1084,7 @@
    * @param typeName the name of the type that cannot be extended
    * @see #IMPLEMENTS_DISALLOWED_CLASS
    */
-  static final CompileTimeErrorCode EXTENDS_DISALLOWED_CLASS = new CompileTimeErrorCode.con1('EXTENDS_DISALLOWED_CLASS', 43, "Classes cannot extend '%s'");
+  static final CompileTimeErrorCode EXTENDS_DISALLOWED_CLASS = new CompileTimeErrorCode.con1('EXTENDS_DISALLOWED_CLASS', 46, "Classes cannot extend '%s'");
 
   /**
    * 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m &lt; h</i> or if <i>m &gt;
@@ -1077,21 +1096,21 @@
    * @param requiredCount the maximum number of positional arguments
    * @param argumentCount the actual number of positional arguments given
    */
-  static final CompileTimeErrorCode EXTRA_POSITIONAL_ARGUMENTS = new CompileTimeErrorCode.con1('EXTRA_POSITIONAL_ARGUMENTS', 44, "%d positional arguments expected, but %d found");
+  static final CompileTimeErrorCode EXTRA_POSITIONAL_ARGUMENTS = new CompileTimeErrorCode.con1('EXTRA_POSITIONAL_ARGUMENTS', 47, "%d positional arguments expected, but %d found");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile time
    * error if more than one initializer corresponding to a given instance variable appears in
    * <i>k</i>'s list.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS = new CompileTimeErrorCode.con1('FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS', 45, "The field '%s' cannot be initialized twice in the same constructor");
+  static final CompileTimeErrorCode FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS = new CompileTimeErrorCode.con1('FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS', 48, "The field '%s' cannot be initialized twice in the same constructor");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile time
    * error if <i>k</i>'s initializer list contains an initializer for a variable that is initialized
    * by means of an initializing formal of <i>k</i>.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER = new CompileTimeErrorCode.con1('FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER', 46, "Fields cannot be initialized in both the parameter list and the initializers");
+  static final CompileTimeErrorCode FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER = new CompileTimeErrorCode.con1('FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER', 49, "Fields cannot be initialized in both the parameter list and the initializers");
 
   /**
    * 5 Variables: It is a compile-time error if a final instance variable that has is initialized by
@@ -1100,19 +1119,19 @@
    *
    * @param name the name of the field in question
    */
-  static final CompileTimeErrorCode FINAL_INITIALIZED_MULTIPLE_TIMES = new CompileTimeErrorCode.con1('FINAL_INITIALIZED_MULTIPLE_TIMES', 47, "'%s' is a final field and so can only be set once");
+  static final CompileTimeErrorCode FINAL_INITIALIZED_MULTIPLE_TIMES = new CompileTimeErrorCode.con1('FINAL_INITIALIZED_MULTIPLE_TIMES', 50, "'%s' is a final field and so can only be set once");
 
   /**
    * 7.6.1 Generative Constructors: It is a compile-time error if an initializing formal is used by
    * a function other than a non-redirecting generative constructor.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZER_FACTORY_CONSTRUCTOR = new CompileTimeErrorCode.con1('FIELD_INITIALIZER_FACTORY_CONSTRUCTOR', 48, "Initializing formal fields cannot be used in factory constructors");
+  static final CompileTimeErrorCode FIELD_INITIALIZER_FACTORY_CONSTRUCTOR = new CompileTimeErrorCode.con1('FIELD_INITIALIZER_FACTORY_CONSTRUCTOR', 51, "Initializing formal fields cannot be used in factory constructors");
 
   /**
    * 7.6.1 Generative Constructors: It is a compile-time error if an initializing formal is used by
    * a function other than a non-redirecting generative constructor.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new CompileTimeErrorCode.con1('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 49, "Initializing formal fields can only be used in constructors");
+  static final CompileTimeErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new CompileTimeErrorCode.con1('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 52, "Initializing formal fields can only be used in constructors");
 
   /**
    * 7.6.1 Generative Constructors: A generative constructor may be redirecting, in which case its
@@ -1121,7 +1140,7 @@
    * 7.6.1 Generative Constructors: It is a compile-time error if an initializing formal is used by
    * a function other than a non-redirecting generative constructor.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR = new CompileTimeErrorCode.con1('FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR', 50, "The redirecting constructor cannot have a field initializer");
+  static final CompileTimeErrorCode FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR = new CompileTimeErrorCode.con1('FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR', 53, "The redirecting constructor cannot have a field initializer");
 
   /**
    * 7.2 Getters: It is a compile-time error if a class has both a getter and a method with the same
@@ -1129,7 +1148,7 @@
    *
    * @param name the conflicting name of the getter and method
    */
-  static final CompileTimeErrorCode GETTER_AND_METHOD_WITH_SAME_NAME = new CompileTimeErrorCode.con1('GETTER_AND_METHOD_WITH_SAME_NAME', 51, "'%s' cannot be used to name a getter, there is already a method with the same name");
+  static final CompileTimeErrorCode GETTER_AND_METHOD_WITH_SAME_NAME = new CompileTimeErrorCode.con1('GETTER_AND_METHOD_WITH_SAME_NAME', 54, "'%s' cannot be used to name a getter, there is already a method with the same name");
 
   /**
    * 12.2 Null: It is a compile-time error for a class to attempt to extend or implement Null.
@@ -1148,13 +1167,13 @@
    * @param typeName the name of the type that cannot be implemented
    * @see #EXTENDS_DISALLOWED_CLASS
    */
-  static final CompileTimeErrorCode IMPLEMENTS_DISALLOWED_CLASS = new CompileTimeErrorCode.con1('IMPLEMENTS_DISALLOWED_CLASS', 52, "Classes cannot implement '%s'");
+  static final CompileTimeErrorCode IMPLEMENTS_DISALLOWED_CLASS = new CompileTimeErrorCode.con1('IMPLEMENTS_DISALLOWED_CLASS', 55, "Classes cannot implement '%s'");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the implements clause of a class includes
    * type dynamic.
    */
-  static final CompileTimeErrorCode IMPLEMENTS_DYNAMIC = new CompileTimeErrorCode.con1('IMPLEMENTS_DYNAMIC', 53, "Classes cannot implement 'dynamic'");
+  static final CompileTimeErrorCode IMPLEMENTS_DYNAMIC = new CompileTimeErrorCode.con1('IMPLEMENTS_DYNAMIC', 56, "Classes cannot implement 'dynamic'");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the implements clause of a class <i>C</i>
@@ -1163,7 +1182,7 @@
    *
    * @param typeName the name of the interface that was not found
    */
-  static final CompileTimeErrorCode IMPLEMENTS_NON_CLASS = new CompileTimeErrorCode.con1('IMPLEMENTS_NON_CLASS', 54, "Classes can only implement other classes");
+  static final CompileTimeErrorCode IMPLEMENTS_NON_CLASS = new CompileTimeErrorCode.con1('IMPLEMENTS_NON_CLASS', 57, "Classes can only implement other classes");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if a type <i>T</i> appears more than once in
@@ -1171,7 +1190,7 @@
    *
    * @param className the name of the class that is implemented more than once
    */
-  static final CompileTimeErrorCode IMPLEMENTS_REPEATED = new CompileTimeErrorCode.con1('IMPLEMENTS_REPEATED', 55, "'%s' can only be implemented once");
+  static final CompileTimeErrorCode IMPLEMENTS_REPEATED = new CompileTimeErrorCode.con1('IMPLEMENTS_REPEATED', 58, "'%s' can only be implemented once");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the superclass of a class <i>C</i> appears
@@ -1179,7 +1198,7 @@
    *
    * @param className the name of the class that appears in both "extends" and "implements" clauses
    */
-  static final CompileTimeErrorCode IMPLEMENTS_SUPER_CLASS = new CompileTimeErrorCode.con1('IMPLEMENTS_SUPER_CLASS', 56, "'%s' cannot be used in both 'extends' and 'implements' clauses");
+  static final CompileTimeErrorCode IMPLEMENTS_SUPER_CLASS = new CompileTimeErrorCode.con1('IMPLEMENTS_SUPER_CLASS', 59, "'%s' cannot be used in both 'extends' and 'implements' clauses");
 
   /**
    * 7.6.1 Generative Constructors: Note that <b>this</b> is not in scope on the right hand side of
@@ -1191,14 +1210,14 @@
    *
    * @param name the name of the type in question
    */
-  static final CompileTimeErrorCode IMPLICIT_THIS_REFERENCE_IN_INITIALIZER = new CompileTimeErrorCode.con1('IMPLICIT_THIS_REFERENCE_IN_INITIALIZER', 57, "Only static members can be accessed in initializers");
+  static final CompileTimeErrorCode IMPLICIT_THIS_REFERENCE_IN_INITIALIZER = new CompileTimeErrorCode.con1('IMPLICIT_THIS_REFERENCE_IN_INITIALIZER', 60, "Only static members can be accessed in initializers");
 
   /**
    * SDK implementation libraries can be imported only by other SDK libraries.
    *
    * @param uri the uri pointing to a library
    */
-  static final CompileTimeErrorCode IMPORT_INTERNAL_LIBRARY = new CompileTimeErrorCode.con1('IMPORT_INTERNAL_LIBRARY', 58, "The library '%s' is internal and cannot be imported");
+  static final CompileTimeErrorCode IMPORT_INTERNAL_LIBRARY = new CompileTimeErrorCode.con1('IMPORT_INTERNAL_LIBRARY', 61, "The library '%s' is internal and cannot be imported");
 
   /**
    * 14.1 Imports: It is a compile-time error if the compilation unit found at the specified URI is
@@ -1206,7 +1225,7 @@
    *
    * @param uri the uri pointing to a non-library declaration
    */
-  static final CompileTimeErrorCode IMPORT_OF_NON_LIBRARY = new CompileTimeErrorCode.con1('IMPORT_OF_NON_LIBRARY', 59, "The imported library '%s' must not have a part-of directive");
+  static final CompileTimeErrorCode IMPORT_OF_NON_LIBRARY = new CompileTimeErrorCode.con1('IMPORT_OF_NON_LIBRARY', 62, "The imported library '%s' must not have a part-of directive");
 
   /**
    * 13.9 Switch: It is a compile-time error if values of the expressions <i>e<sub>k</sub></i> are
@@ -1215,7 +1234,7 @@
    * @param expressionSource the expression source code that is the unexpected type
    * @param expectedType the name of the expected type
    */
-  static final CompileTimeErrorCode INCONSISTENT_CASE_EXPRESSION_TYPES = new CompileTimeErrorCode.con1('INCONSISTENT_CASE_EXPRESSION_TYPES', 60, "Case expressions must have the same types, '%s' is not a %s'");
+  static final CompileTimeErrorCode INCONSISTENT_CASE_EXPRESSION_TYPES = new CompileTimeErrorCode.con1('INCONSISTENT_CASE_EXPRESSION_TYPES', 63, "Case expressions must have the same types, '%s' is not a %s'");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile-time
@@ -1226,7 +1245,7 @@
    *          immediately enclosing class
    * @see #INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD
    */
-  static final CompileTimeErrorCode INITIALIZER_FOR_NON_EXISTANT_FIELD = new CompileTimeErrorCode.con1('INITIALIZER_FOR_NON_EXISTANT_FIELD', 61, "'%s' is not a variable in the enclosing class");
+  static final CompileTimeErrorCode INITIALIZER_FOR_NON_EXISTANT_FIELD = new CompileTimeErrorCode.con1('INITIALIZER_FOR_NON_EXISTANT_FIELD', 64, "'%s' is not a variable in the enclosing class");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile-time
@@ -1237,7 +1256,7 @@
    *          enclosing class
    * @see #INITIALIZING_FORMAL_FOR_STATIC_FIELD
    */
-  static final CompileTimeErrorCode INITIALIZER_FOR_STATIC_FIELD = new CompileTimeErrorCode.con1('INITIALIZER_FOR_STATIC_FIELD', 62, "'%s' is a static variable in the enclosing class, variables initialized in a constructor cannot be static");
+  static final CompileTimeErrorCode INITIALIZER_FOR_STATIC_FIELD = new CompileTimeErrorCode.con1('INITIALIZER_FOR_STATIC_FIELD', 65, "'%s' is a static variable in the enclosing class, variables initialized in a constructor cannot be static");
 
   /**
    * 7.6.1 Generative Constructors: An initializing formal has the form <i>this.id</i>. It is a
@@ -1249,7 +1268,7 @@
    * @see #INITIALIZING_FORMAL_FOR_STATIC_FIELD
    * @see #INITIALIZER_FOR_NON_EXISTANT_FIELD
    */
-  static final CompileTimeErrorCode INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD = new CompileTimeErrorCode.con1('INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD', 63, "'%s' is not a variable in the enclosing class");
+  static final CompileTimeErrorCode INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD = new CompileTimeErrorCode.con1('INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD', 66, "'%s' is not a variable in the enclosing class");
 
   /**
    * 7.6.1 Generative Constructors: An initializing formal has the form <i>this.id</i>. It is a
@@ -1260,20 +1279,20 @@
    *          enclosing class
    * @see #INITIALIZER_FOR_STATIC_FIELD
    */
-  static final CompileTimeErrorCode INITIALIZING_FORMAL_FOR_STATIC_FIELD = new CompileTimeErrorCode.con1('INITIALIZING_FORMAL_FOR_STATIC_FIELD', 64, "'%s' is a static variable in the enclosing class, variables initialized in a constructor cannot be static");
+  static final CompileTimeErrorCode INITIALIZING_FORMAL_FOR_STATIC_FIELD = new CompileTimeErrorCode.con1('INITIALIZING_FORMAL_FOR_STATIC_FIELD', 67, "'%s' is a static variable in the enclosing class, variables initialized in a constructor cannot be static");
 
   /**
    * 12.30 Identifier Reference: Otherwise, e is equivalent to the property extraction
    * <b>this</b>.<i>id</i>.
    */
-  static final CompileTimeErrorCode INSTANCE_MEMBER_ACCESS_FROM_STATIC = new CompileTimeErrorCode.con1('INSTANCE_MEMBER_ACCESS_FROM_STATIC', 65, "Instance member cannot be accessed from static method");
+  static final CompileTimeErrorCode INSTANCE_MEMBER_ACCESS_FROM_STATIC = new CompileTimeErrorCode.con1('INSTANCE_MEMBER_ACCESS_FROM_STATIC', 68, "Instance member cannot be accessed from static method");
 
   /**
    * 11 Metadata: Metadata consists of a series of annotations, each of which begin with the
    * character @, followed by a constant expression that must be either a reference to a
    * compile-time constant variable, or a call to a constant constructor.
    */
-  static final CompileTimeErrorCode INVALID_ANNOTATION = new CompileTimeErrorCode.con1('INVALID_ANNOTATION', 66, "Annotation can be only constant variable or constant constructor invocation");
+  static final CompileTimeErrorCode INVALID_ANNOTATION = new CompileTimeErrorCode.con1('INVALID_ANNOTATION', 69, "Annotation can be only constant variable or constant constructor invocation");
 
   /**
    * TODO(brianwilkerson) Remove this when we have decided on how to report errors in compile-time
@@ -1281,26 +1300,26 @@
    *
    * See TODOs in ConstantVisitor
    */
-  static final CompileTimeErrorCode INVALID_CONSTANT = new CompileTimeErrorCode.con1('INVALID_CONSTANT', 67, "Invalid constant value");
+  static final CompileTimeErrorCode INVALID_CONSTANT = new CompileTimeErrorCode.con1('INVALID_CONSTANT', 70, "Invalid constant value");
 
   /**
    * 7.6 Constructors: It is a compile-time error if the name of a constructor is not a constructor
    * name.
    */
-  static final CompileTimeErrorCode INVALID_CONSTRUCTOR_NAME = new CompileTimeErrorCode.con1('INVALID_CONSTRUCTOR_NAME', 68, "Invalid constructor name");
+  static final CompileTimeErrorCode INVALID_CONSTRUCTOR_NAME = new CompileTimeErrorCode.con1('INVALID_CONSTRUCTOR_NAME', 71, "Invalid constructor name");
 
   /**
    * 7.6.2 Factories: It is a compile-time error if <i>M</i> is not the name of the immediately
    * enclosing class.
    */
-  static final CompileTimeErrorCode INVALID_FACTORY_NAME_NOT_A_CLASS = new CompileTimeErrorCode.con1('INVALID_FACTORY_NAME_NOT_A_CLASS', 69, "The name of the immediately enclosing class expected");
+  static final CompileTimeErrorCode INVALID_FACTORY_NAME_NOT_A_CLASS = new CompileTimeErrorCode.con1('INVALID_FACTORY_NAME_NOT_A_CLASS', 72, "The name of the immediately enclosing class expected");
 
   /**
    * 12.10 This: It is a compile-time error if this appears in a top-level function or variable
    * initializer, in a factory constructor, or in a static method or variable initializer, or in the
    * initializer of an instance variable.
    */
-  static final CompileTimeErrorCode INVALID_REFERENCE_TO_THIS = new CompileTimeErrorCode.con1('INVALID_REFERENCE_TO_THIS', 70, "Invalid reference to 'this' expression");
+  static final CompileTimeErrorCode INVALID_REFERENCE_TO_THIS = new CompileTimeErrorCode.con1('INVALID_REFERENCE_TO_THIS', 73, "Invalid reference to 'this' expression");
 
   /**
    * 12.6 Lists: It is a compile time error if the type argument of a constant list literal includes
@@ -1308,7 +1327,7 @@
    *
    * @name the name of the type parameter
    */
-  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_LIST = new CompileTimeErrorCode.con1('INVALID_TYPE_ARGUMENT_IN_CONST_LIST', 71, "Constant list literals cannot include a type parameter as a type argument, such as '%s'");
+  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_LIST = new CompileTimeErrorCode.con1('INVALID_TYPE_ARGUMENT_IN_CONST_LIST', 74, "Constant list literals cannot include a type parameter as a type argument, such as '%s'");
 
   /**
    * 12.7 Maps: It is a compile time error if the type arguments of a constant map literal include a
@@ -1316,7 +1335,7 @@
    *
    * @name the name of the type parameter
    */
-  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_MAP = new CompileTimeErrorCode.con1('INVALID_TYPE_ARGUMENT_IN_CONST_MAP', 72, "Constant map literals cannot include a type parameter as a type argument, such as '%s'");
+  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_MAP = new CompileTimeErrorCode.con1('INVALID_TYPE_ARGUMENT_IN_CONST_MAP', 75, "Constant map literals cannot include a type parameter as a type argument, such as '%s'");
 
   /**
    * 14.2 Exports: It is a compile-time error if the compilation unit found at the specified URI is
@@ -1331,7 +1350,7 @@
    * @param uri the URI that is invalid
    * @see #URI_DOES_NOT_EXIST
    */
-  static final CompileTimeErrorCode INVALID_URI = new CompileTimeErrorCode.con1('INVALID_URI', 73, "Invalid URI syntax: '%s'");
+  static final CompileTimeErrorCode INVALID_URI = new CompileTimeErrorCode.con1('INVALID_URI', 76, "Invalid URI syntax: '%s'");
 
   /**
    * 13.13 Break: It is a compile-time error if no such statement <i>s<sub>E</sub></i> exists within
@@ -1342,7 +1361,7 @@
    *
    * @param labelName the name of the unresolvable label
    */
-  static final CompileTimeErrorCode LABEL_IN_OUTER_SCOPE = new CompileTimeErrorCode.con1('LABEL_IN_OUTER_SCOPE', 74, "Cannot reference label '%s' declared in an outer method");
+  static final CompileTimeErrorCode LABEL_IN_OUTER_SCOPE = new CompileTimeErrorCode.con1('LABEL_IN_OUTER_SCOPE', 77, "Cannot reference label '%s' declared in an outer method");
 
   /**
    * 13.13 Break: It is a compile-time error if no such statement <i>s<sub>E</sub></i> exists within
@@ -1353,7 +1372,7 @@
    *
    * @param labelName the name of the unresolvable label
    */
-  static final CompileTimeErrorCode LABEL_UNDEFINED = new CompileTimeErrorCode.con1('LABEL_UNDEFINED', 75, "Cannot reference undefined label '%s'");
+  static final CompileTimeErrorCode LABEL_UNDEFINED = new CompileTimeErrorCode.con1('LABEL_UNDEFINED', 78, "Cannot reference undefined label '%s'");
 
   /**
    * 12.6 Lists: A run-time list literal &lt;<i>E</i>&gt; [<i>e<sub>1</sub></i> ...
@@ -1369,7 +1388,7 @@
    * It is a static warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 &lt;=
    * j &lt;= m</i>.
    */
-  static final CompileTimeErrorCode LIST_ELEMENT_TYPE_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('LIST_ELEMENT_TYPE_NOT_ASSIGNABLE', 76, "The element type '%s' cannot be assigned to the list type '%s'");
+  static final CompileTimeErrorCode LIST_ELEMENT_TYPE_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('LIST_ELEMENT_TYPE_NOT_ASSIGNABLE', 79, "The element type '%s' cannot be assigned to the list type '%s'");
 
   /**
    * 12.7 Map: A run-time map literal &lt;<i>K</i>, <i>V</i>&gt; [<i>k<sub>1</sub></i> :
@@ -1385,7 +1404,7 @@
    * It is a static warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 &lt;=
    * j &lt;= m</i>.
    */
-  static final CompileTimeErrorCode MAP_KEY_TYPE_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('MAP_KEY_TYPE_NOT_ASSIGNABLE', 77, "The element type '%s' cannot be assigned to the map key type '%s'");
+  static final CompileTimeErrorCode MAP_KEY_TYPE_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('MAP_KEY_TYPE_NOT_ASSIGNABLE', 80, "The element type '%s' cannot be assigned to the map key type '%s'");
 
   /**
    * 12.7 Map: A run-time map literal &lt;<i>K</i>, <i>V</i>&gt; [<i>k<sub>1</sub></i> :
@@ -1401,13 +1420,13 @@
    * It is a static warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 &lt;=
    * j &lt;= m</i>.
    */
-  static final CompileTimeErrorCode MAP_VALUE_TYPE_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('MAP_VALUE_TYPE_NOT_ASSIGNABLE', 78, "The element type '%s' cannot be assigned to the map value type '%s'");
+  static final CompileTimeErrorCode MAP_VALUE_TYPE_NOT_ASSIGNABLE = new CompileTimeErrorCode.con1('MAP_VALUE_TYPE_NOT_ASSIGNABLE', 81, "The element type '%s' cannot be assigned to the map value type '%s'");
 
   /**
    * 7 Classes: It is a compile time error if a class <i>C</i> declares a member with the same name
    * as <i>C</i>.
    */
-  static final CompileTimeErrorCode MEMBER_WITH_CLASS_NAME = new CompileTimeErrorCode.con1('MEMBER_WITH_CLASS_NAME', 79, "Class members cannot have the same name as the enclosing class");
+  static final CompileTimeErrorCode MEMBER_WITH_CLASS_NAME = new CompileTimeErrorCode.con1('MEMBER_WITH_CLASS_NAME', 82, "Class members cannot have the same name as the enclosing class");
 
   /**
    * 7.2 Getters: It is a compile-time error if a class has both a getter and a method with the same
@@ -1415,17 +1434,17 @@
    *
    * @param name the conflicting name of the getter and method
    */
-  static final CompileTimeErrorCode METHOD_AND_GETTER_WITH_SAME_NAME = new CompileTimeErrorCode.con1('METHOD_AND_GETTER_WITH_SAME_NAME', 80, "'%s' cannot be used to name a method, there is already a getter with the same name");
+  static final CompileTimeErrorCode METHOD_AND_GETTER_WITH_SAME_NAME = new CompileTimeErrorCode.con1('METHOD_AND_GETTER_WITH_SAME_NAME', 83, "'%s' cannot be used to name a method, there is already a getter with the same name");
 
   /**
    * 12.1 Constants: A constant expression is ... a constant list literal.
    */
-  static final CompileTimeErrorCode MISSING_CONST_IN_LIST_LITERAL = new CompileTimeErrorCode.con1('MISSING_CONST_IN_LIST_LITERAL', 81, "List literals must be prefixed with 'const' when used as a constant expression");
+  static final CompileTimeErrorCode MISSING_CONST_IN_LIST_LITERAL = new CompileTimeErrorCode.con1('MISSING_CONST_IN_LIST_LITERAL', 84, "List literals must be prefixed with 'const' when used as a constant expression");
 
   /**
    * 12.1 Constants: A constant expression is ... a constant map literal.
    */
-  static final CompileTimeErrorCode MISSING_CONST_IN_MAP_LITERAL = new CompileTimeErrorCode.con1('MISSING_CONST_IN_MAP_LITERAL', 82, "Map literals must be prefixed with 'const' when used as a constant expression");
+  static final CompileTimeErrorCode MISSING_CONST_IN_MAP_LITERAL = new CompileTimeErrorCode.con1('MISSING_CONST_IN_MAP_LITERAL', 85, "Map literals must be prefixed with 'const' when used as a constant expression");
 
   /**
    * 9 Mixins: It is a compile-time error if a declared or derived mixin explicitly declares a
@@ -1433,7 +1452,7 @@
    *
    * @param typeName the name of the mixin that is invalid
    */
-  static final CompileTimeErrorCode MIXIN_DECLARES_CONSTRUCTOR = new CompileTimeErrorCode.con1('MIXIN_DECLARES_CONSTRUCTOR', 83, "The class '%s' cannot be used as a mixin because it declares a constructor");
+  static final CompileTimeErrorCode MIXIN_DECLARES_CONSTRUCTOR = new CompileTimeErrorCode.con1('MIXIN_DECLARES_CONSTRUCTOR', 86, "The class '%s' cannot be used as a mixin because it declares a constructor");
 
   /**
    * 9 Mixins: It is a compile-time error if a mixin is derived from a class whose superclass is not
@@ -1441,7 +1460,7 @@
    *
    * @param typeName the name of the mixin that is invalid
    */
-  static final CompileTimeErrorCode MIXIN_INHERITS_FROM_NOT_OBJECT = new CompileTimeErrorCode.con1('MIXIN_INHERITS_FROM_NOT_OBJECT', 84, "The class '%s' cannot be used as a mixin because it extends a class other than Object");
+  static final CompileTimeErrorCode MIXIN_INHERITS_FROM_NOT_OBJECT = new CompileTimeErrorCode.con1('MIXIN_INHERITS_FROM_NOT_OBJECT', 87, "The class '%s' cannot be used as a mixin because it extends a class other than Object");
 
   /**
    * 12.2 Null: It is a compile-time error for a class to attempt to extend or implement Null.
@@ -1460,43 +1479,43 @@
    * @param typeName the name of the type that cannot be extended
    * @see #IMPLEMENTS_DISALLOWED_CLASS
    */
-  static final CompileTimeErrorCode MIXIN_OF_DISALLOWED_CLASS = new CompileTimeErrorCode.con1('MIXIN_OF_DISALLOWED_CLASS', 85, "Classes cannot mixin '%s'");
+  static final CompileTimeErrorCode MIXIN_OF_DISALLOWED_CLASS = new CompileTimeErrorCode.con1('MIXIN_OF_DISALLOWED_CLASS', 88, "Classes cannot mixin '%s'");
 
   /**
    * 9.1 Mixin Application: It is a compile-time error if <i>M</i> does not denote a class or mixin
    * available in the immediately enclosing scope.
    */
-  static final CompileTimeErrorCode MIXIN_OF_NON_CLASS = new CompileTimeErrorCode.con1('MIXIN_OF_NON_CLASS', 86, "Classes can only mixin other classes");
+  static final CompileTimeErrorCode MIXIN_OF_NON_CLASS = new CompileTimeErrorCode.con1('MIXIN_OF_NON_CLASS', 89, "Classes can only mixin other classes");
 
   /**
    * 9 Mixins: It is a compile-time error if a declared or derived mixin refers to super.
    */
-  static final CompileTimeErrorCode MIXIN_REFERENCES_SUPER = new CompileTimeErrorCode.con1('MIXIN_REFERENCES_SUPER', 87, "The class '%s' cannot be used as a mixin because it references 'super'");
+  static final CompileTimeErrorCode MIXIN_REFERENCES_SUPER = new CompileTimeErrorCode.con1('MIXIN_REFERENCES_SUPER', 90, "The class '%s' cannot be used as a mixin because it references 'super'");
 
   /**
    * 9.1 Mixin Application: It is a compile-time error if <i>S</i> does not denote a class available
    * in the immediately enclosing scope.
    */
-  static final CompileTimeErrorCode MIXIN_WITH_NON_CLASS_SUPERCLASS = new CompileTimeErrorCode.con1('MIXIN_WITH_NON_CLASS_SUPERCLASS', 88, "Mixin can only be applied to class");
+  static final CompileTimeErrorCode MIXIN_WITH_NON_CLASS_SUPERCLASS = new CompileTimeErrorCode.con1('MIXIN_WITH_NON_CLASS_SUPERCLASS', 91, "Mixin can only be applied to class");
 
   /**
    * 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 MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS = new CompileTimeErrorCode.con1('MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS', 89, "Constructor may have at most one 'this' redirection");
+  static final CompileTimeErrorCode MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS = new CompileTimeErrorCode.con1('MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS', 92, "Constructor may have at most one 'this' redirection");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. Then <i>k</i> may
    * include at most one superinitializer in its initializer list or a compile time error occurs.
    */
-  static final CompileTimeErrorCode MULTIPLE_SUPER_INITIALIZERS = new CompileTimeErrorCode.con1('MULTIPLE_SUPER_INITIALIZERS', 90, "Constructor may have at most one 'super' initializer");
+  static final CompileTimeErrorCode MULTIPLE_SUPER_INITIALIZERS = new CompileTimeErrorCode.con1('MULTIPLE_SUPER_INITIALIZERS', 93, "Constructor may have at most one 'super' initializer");
 
   /**
    * 11 Metadata: Metadata consists of a series of annotations, each of which begin with the
    * character @, followed by a constant expression that must be either a reference to a
    * compile-time constant variable, or a call to a constant constructor.
    */
-  static final CompileTimeErrorCode NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS = new CompileTimeErrorCode.con1('NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS', 91, "Annotation creation must have arguments");
+  static final CompileTimeErrorCode NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS = new CompileTimeErrorCode.con1('NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS', 94, "Annotation creation must have arguments");
 
   /**
    * 7.6.1 Generative Constructors: If no superinitializer is provided, an implicit superinitializer
@@ -1506,7 +1525,7 @@
    * 7.6.1 Generative constructors. It is 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 NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT = new CompileTimeErrorCode.con1('NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT', 92, "The class '%s' does not have a default constructor");
+  static final CompileTimeErrorCode NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT = new CompileTimeErrorCode.con1('NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT', 95, "The class '%s' does not have a default constructor");
 
   /**
    * 7.6 Constructors: Iff no constructor is specified for a class <i>C</i>, it implicitly has a
@@ -1515,13 +1534,13 @@
    * 7.6.1 Generative constructors. It is 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 NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT = new CompileTimeErrorCode.con1('NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT', 93, "The class '%s' does not have a default constructor");
+  static final CompileTimeErrorCode NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT = new CompileTimeErrorCode.con1('NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT', 96, "The class '%s' does not have a default constructor");
 
   /**
    * 13.2 Expression Statements: It is a compile-time error if a non-constant map literal that has
    * no explicit type arguments appears in a place where a statement is expected.
    */
-  static final CompileTimeErrorCode NON_CONST_MAP_AS_EXPRESSION_STATEMENT = new CompileTimeErrorCode.con1('NON_CONST_MAP_AS_EXPRESSION_STATEMENT', 94, "A non-constant map literal without type arguments cannot be used as an expression statement");
+  static final CompileTimeErrorCode NON_CONST_MAP_AS_EXPRESSION_STATEMENT = new CompileTimeErrorCode.con1('NON_CONST_MAP_AS_EXPRESSION_STATEMENT', 97, "A non-constant map literal without type arguments cannot be used as an expression statement");
 
   /**
    * 13.9 Switch: Given a switch statement of the form <i>switch (e) { label<sub>11</sub> &hellip;
@@ -1532,44 +1551,44 @@
    * s<sub>n</sub>}</i>, it is a compile-time error if the expressions <i>e<sub>k</sub></i> are not
    * compile-time constants, for all <i>1 &lt;= k &lt;= n</i>.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_CASE_EXPRESSION = new CompileTimeErrorCode.con1('NON_CONSTANT_CASE_EXPRESSION', 95, "Case expressions must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_CASE_EXPRESSION = new CompileTimeErrorCode.con1('NON_CONSTANT_CASE_EXPRESSION', 98, "Case expressions must be constant");
 
   /**
    * 6.2.2 Optional Formals: It is a compile-time error if the default value of an optional
    * parameter is not a compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_DEFAULT_VALUE = new CompileTimeErrorCode.con1('NON_CONSTANT_DEFAULT_VALUE', 96, "Default values of an optional parameter must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_DEFAULT_VALUE = new CompileTimeErrorCode.con1('NON_CONSTANT_DEFAULT_VALUE', 99, "Default values of an optional parameter must be constant");
 
   /**
    * 12.6 Lists: It is a compile time error if an element of a constant list literal is not a
    * compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_LIST_ELEMENT = new CompileTimeErrorCode.con1('NON_CONSTANT_LIST_ELEMENT', 97, "'const' lists must have all constant values");
+  static final CompileTimeErrorCode NON_CONSTANT_LIST_ELEMENT = new CompileTimeErrorCode.con1('NON_CONSTANT_LIST_ELEMENT', 100, "'const' lists must have all constant values");
 
   /**
    * 12.7 Maps: It is a compile time error if either a key or a value of an entry in a constant map
    * literal is not a compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_MAP_KEY = new CompileTimeErrorCode.con1('NON_CONSTANT_MAP_KEY', 98, "The keys in a map must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_MAP_KEY = new CompileTimeErrorCode.con1('NON_CONSTANT_MAP_KEY', 101, "The keys in a map must be constant");
 
   /**
    * 12.7 Maps: It is a compile time error if either a key or a value of an entry in a constant map
    * literal is not a compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_MAP_VALUE = new CompileTimeErrorCode.con1('NON_CONSTANT_MAP_VALUE', 99, "The values in a 'const' map must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_MAP_VALUE = new CompileTimeErrorCode.con1('NON_CONSTANT_MAP_VALUE', 102, "The values in a 'const' map must be constant");
 
   /**
    * 11 Metadata: Metadata consists of a series of annotations, each of which begin with the
    * character @, followed by a constant expression that must be either a reference to a
    * compile-time constant variable, or a call to a constant constructor.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_ANNOTATION_CONSTRUCTOR = new CompileTimeErrorCode.con1('NON_CONSTANT_ANNOTATION_CONSTRUCTOR', 100, "Annotation creation can use only 'const' constructor");
+  static final CompileTimeErrorCode NON_CONSTANT_ANNOTATION_CONSTRUCTOR = new CompileTimeErrorCode.con1('NON_CONSTANT_ANNOTATION_CONSTRUCTOR', 103, "Annotation creation can use only 'const' constructor");
 
   /**
    * 7.6.3 Constant Constructors: Any expression that appears within the initializer list of a
    * constant constructor must be a potentially constant expression, or a compile-time error occurs.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_VALUE_IN_INITIALIZER = new CompileTimeErrorCode.con1('NON_CONSTANT_VALUE_IN_INITIALIZER', 101, "Initializer expressions in constant constructors must be constants");
+  static final CompileTimeErrorCode NON_CONSTANT_VALUE_IN_INITIALIZER = new CompileTimeErrorCode.con1('NON_CONSTANT_VALUE_IN_INITIALIZER', 104, "Initializer expressions in constant constructors must be constants");
 
   /**
    * 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m < h</i> or if <i>m > n</i>.
@@ -1580,7 +1599,7 @@
    * @param requiredCount the expected number of required arguments
    * @param argumentCount the actual number of positional arguments given
    */
-  static final CompileTimeErrorCode NOT_ENOUGH_REQUIRED_ARGUMENTS = new CompileTimeErrorCode.con1('NOT_ENOUGH_REQUIRED_ARGUMENTS', 102, "%d required argument(s) expected, but %d found");
+  static final CompileTimeErrorCode NOT_ENOUGH_REQUIRED_ARGUMENTS = new CompileTimeErrorCode.con1('NOT_ENOUGH_REQUIRED_ARGUMENTS', 105, "%d required argument(s) expected, but %d found");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1588,17 +1607,17 @@
    * 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 NON_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode.con1('NON_GENERATIVE_CONSTRUCTOR', 103, "The generative constructor '%s' expected, but factory found");
+  static final CompileTimeErrorCode NON_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode.con1('NON_GENERATIVE_CONSTRUCTOR', 106, "The generative constructor '%s' expected, but factory found");
 
   /**
    * 7.9 Superclasses: It is a compile-time error to specify an extends clause for class Object.
    */
-  static final CompileTimeErrorCode OBJECT_CANNOT_EXTEND_ANOTHER_CLASS = new CompileTimeErrorCode.con1('OBJECT_CANNOT_EXTEND_ANOTHER_CLASS', 104, "");
+  static final CompileTimeErrorCode OBJECT_CANNOT_EXTEND_ANOTHER_CLASS = new CompileTimeErrorCode.con1('OBJECT_CANNOT_EXTEND_ANOTHER_CLASS', 107, "");
 
   /**
    * 7.1.1 Operators: It is a compile-time error to declare an optional parameter in an operator.
    */
-  static final CompileTimeErrorCode OPTIONAL_PARAMETER_IN_OPERATOR = new CompileTimeErrorCode.con1('OPTIONAL_PARAMETER_IN_OPERATOR', 105, "Optional parameters are not allowed when defining an operator");
+  static final CompileTimeErrorCode OPTIONAL_PARAMETER_IN_OPERATOR = new CompileTimeErrorCode.con1('OPTIONAL_PARAMETER_IN_OPERATOR', 108, "Optional parameters are not allowed when defining an operator");
 
   /**
    * 14.3 Parts: It is a compile time error if the contents of the URI are not a valid part
@@ -1606,25 +1625,25 @@
    *
    * @param uri the uri pointing to a non-library declaration
    */
-  static final CompileTimeErrorCode PART_OF_NON_PART = new CompileTimeErrorCode.con1('PART_OF_NON_PART', 106, "The included part '%s' must have a part-of directive");
+  static final CompileTimeErrorCode PART_OF_NON_PART = new CompileTimeErrorCode.con1('PART_OF_NON_PART', 109, "The included part '%s' must have a part-of directive");
 
   /**
    * 14.1 Imports: It is a compile-time error if the current library declares a top-level member
    * named <i>p</i>.
    */
-  static final CompileTimeErrorCode PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER = new CompileTimeErrorCode.con1('PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER', 107, "The name '%s' is already used as an import prefix and cannot be used to name a top-level element");
+  static final CompileTimeErrorCode PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER = new CompileTimeErrorCode.con1('PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER', 110, "The name '%s' is already used as an import prefix and cannot be used to name a top-level element");
 
   /**
    * 6.2.2 Optional Formals: It is a compile-time error if the name of a named optional parameter
    * begins with an '_' character.
    */
-  static final CompileTimeErrorCode PRIVATE_OPTIONAL_PARAMETER = new CompileTimeErrorCode.con1('PRIVATE_OPTIONAL_PARAMETER', 108, "Named optional parameters cannot start with an underscore");
+  static final CompileTimeErrorCode PRIVATE_OPTIONAL_PARAMETER = new CompileTimeErrorCode.con1('PRIVATE_OPTIONAL_PARAMETER', 111, "Named optional parameters cannot start with an underscore");
 
   /**
    * 12.1 Constants: It is a compile-time error if the value of a compile-time constant expression
    * depends on itself.
    */
-  static final CompileTimeErrorCode RECURSIVE_COMPILE_TIME_CONSTANT = new CompileTimeErrorCode.con1('RECURSIVE_COMPILE_TIME_CONSTANT', 109, "");
+  static final CompileTimeErrorCode RECURSIVE_COMPILE_TIME_CONSTANT = new CompileTimeErrorCode.con1('RECURSIVE_COMPILE_TIME_CONSTANT', 112, "");
 
   /**
    * 7.6.1 Generative Constructors: A generative constructor may be redirecting, in which case its
@@ -1635,13 +1654,13 @@
    *
    * https://code.google.com/p/dart/issues/detail?id=954
    */
-  static final CompileTimeErrorCode RECURSIVE_CONSTRUCTOR_REDIRECT = new CompileTimeErrorCode.con1('RECURSIVE_CONSTRUCTOR_REDIRECT', 110, "Cycle in redirecting generative constructors");
+  static final CompileTimeErrorCode RECURSIVE_CONSTRUCTOR_REDIRECT = new CompileTimeErrorCode.con1('RECURSIVE_CONSTRUCTOR_REDIRECT', 113, "Cycle in redirecting generative constructors");
 
   /**
    * 7.6.2 Factories: It is a compile-time error if a redirecting factory constructor redirects to
    * itself, either directly or indirectly via a sequence of redirections.
    */
-  static final CompileTimeErrorCode RECURSIVE_FACTORY_REDIRECT = new CompileTimeErrorCode.con1('RECURSIVE_FACTORY_REDIRECT', 111, "Cycle in redirecting factory constructors");
+  static final CompileTimeErrorCode RECURSIVE_FACTORY_REDIRECT = new CompileTimeErrorCode.con1('RECURSIVE_FACTORY_REDIRECT', 114, "Cycle in redirecting factory constructors");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the interface of a class <i>C</i> is a
@@ -1654,7 +1673,7 @@
    * @param className the name of the class that implements itself recursively
    * @param strImplementsPath a string representation of the implements loop
    */
-  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE = new CompileTimeErrorCode.con1('RECURSIVE_INTERFACE_INHERITANCE', 112, "'%s' cannot be a superinterface of itself: %s");
+  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE = new CompileTimeErrorCode.con1('RECURSIVE_INTERFACE_INHERITANCE', 115, "'%s' cannot be a superinterface of itself: %s");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the interface of a class <i>C</i> is a
@@ -1666,7 +1685,7 @@
    *
    * @param className the name of the class that implements itself recursively
    */
-  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS = new CompileTimeErrorCode.con1('RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS', 113, "'%s' cannot extend itself");
+  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS = new CompileTimeErrorCode.con1('RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS', 116, "'%s' cannot extend itself");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the interface of a class <i>C</i> is a
@@ -1678,31 +1697,31 @@
    *
    * @param className the name of the class that implements itself recursively
    */
-  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS = new CompileTimeErrorCode.con1('RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS', 114, "'%s' cannot implement itself");
+  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS = new CompileTimeErrorCode.con1('RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS', 117, "'%s' cannot implement itself");
 
   /**
    * 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', 115, "Constant factory constructor cannot delegate to a non-constant constructor");
+  static final CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR = new CompileTimeErrorCode.con1('REDIRECT_TO_NON_CONST_CONSTRUCTOR', 118, "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', 116, "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', 119, "The name '%s' cannot be referenced in the initializer of a variable with the same name");
 
   /**
    * 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', 117, "rethrow must be inside of a catch clause");
+  static final CompileTimeErrorCode RETHROW_OUTSIDE_CATCH = new CompileTimeErrorCode.con1('RETHROW_OUTSIDE_CATCH', 120, "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', 118, "Constructors cannot return a value");
+  static final CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode.con1('RETURN_IN_GENERATIVE_CONSTRUCTOR', 121, "Constructors cannot return a value");
 
   /**
    * 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -1712,19 +1731,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', 119, "Invalid context for 'super' invocation");
+  static final CompileTimeErrorCode SUPER_IN_INVALID_CONTEXT = new CompileTimeErrorCode.con1('SUPER_IN_INVALID_CONTEXT', 122, "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', 120, "The redirecting constructor cannot have a 'super' initializer");
+  static final CompileTimeErrorCode SUPER_IN_REDIRECTING_CONSTRUCTOR = new CompileTimeErrorCode.con1('SUPER_IN_REDIRECTING_CONSTRUCTOR', 123, "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', 121, "");
+  static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode.con1('SUPER_INITIALIZER_IN_OBJECT', 124, "");
 
   /**
    * 12.11 Instance Creation: It is a static type warning if any of the type arguments to a
@@ -1743,19 +1762,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', 122, "'%s' does not extend '%s'");
+  static final CompileTimeErrorCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new CompileTimeErrorCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 125, "'%s' does not extend '%s'");
 
   /**
    * 15.3.1 Typedef: It is a compile-time error if a typedef refers to itself via a chain of
    * references that does not include a class declaration.
    */
-  static final CompileTimeErrorCode TYPE_ALIAS_CANNOT_REFERENCE_ITSELF = new CompileTimeErrorCode.con1('TYPE_ALIAS_CANNOT_REFERENCE_ITSELF', 123, "Type alias can reference itself only via the bounds of its generic parameters");
+  static final CompileTimeErrorCode TYPE_ALIAS_CANNOT_REFERENCE_ITSELF = new CompileTimeErrorCode.con1('TYPE_ALIAS_CANNOT_REFERENCE_ITSELF', 126, "Type alias can reference itself only via the bounds of its generic parameters");
 
   /**
    * 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', 124, "Undefined class '%s'");
+  static final CompileTimeErrorCode UNDEFINED_CLASS = new CompileTimeErrorCode.con1('UNDEFINED_CLASS', 127, "Undefined class '%s'");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1763,7 +1782,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', 125, "The class '%s' does not have a generative constructor '%s'");
+  static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 128, "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
@@ -1771,7 +1790,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', 126, "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', 129, "The class '%s' does not have a default generative constructor");
 
   /**
    * 12.14.3 Unqualified Invocation: If there exists a lexically visible declaration named
@@ -1781,7 +1800,7 @@
    *
    * @param methodName the name of the method that is undefined
    */
-  static final CompileTimeErrorCode UNDEFINED_FUNCTION = new CompileTimeErrorCode.con1('UNDEFINED_FUNCTION', 127, "The function '%s' is not defined");
+  static final CompileTimeErrorCode UNDEFINED_FUNCTION = new CompileTimeErrorCode.con1('UNDEFINED_FUNCTION', 130, "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>,
@@ -1793,7 +1812,7 @@
    *
    * @param name the name of the requested named parameter
    */
-  static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode.con1('UNDEFINED_NAMED_PARAMETER', 128, "The named parameter '%s' is not defined");
+  static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode.con1('UNDEFINED_NAMED_PARAMETER', 131, "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
@@ -1808,7 +1827,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', 129, "Target of URI does not exist: '%s'");
+  static final CompileTimeErrorCode URI_DOES_NOT_EXIST = new CompileTimeErrorCode.con1('URI_DOES_NOT_EXIST', 132, "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
@@ -1820,7 +1839,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', 130, "URIs cannot use string interpolation");
+  static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode.con1('URI_WITH_INTERPOLATION', 133, "URIs cannot use string interpolation");
 
   /**
    * 7.1.1 Operators: It is a compile-time error if the arity of the user-declared operator []= is
@@ -1833,7 +1852,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', 131, "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', 134, "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
@@ -1841,13 +1860,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', 132, "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', 135, "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', 133, "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', 136, "Setters should declare exactly one required parameter");
   static final List<CompileTimeErrorCode> values = [
       AMBIGUOUS_EXPORT,
       ARGUMENT_DEFINITION_TEST_NON_PARAMETER,
@@ -1861,6 +1880,8 @@
       CONFLICTING_METHOD_AND_GETTER,
       CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD,
       CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD,
+      CONFLICTING_TYPE_VARIABLE_AND_CLASS,
+      CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
       CONST_CONSTRUCTOR_THROWS_EXCEPTION,
       CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
       CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
@@ -1868,6 +1889,7 @@
       CONST_FORMAL_PARAMETER,
       CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE,
       CONST_INSTANCE_FIELD,
+      CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
       CONST_NOT_INITIALIZED,
       CONST_EVAL_TYPE_BOOL,
       CONST_EVAL_TYPE_BOOL_NUM_STRING,
@@ -2216,13 +2238,28 @@
   static final StaticWarningCode CONCRETE_CLASS_WITH_ABSTRACT_MEMBER = new StaticWarningCode.con1('CONCRETE_CLASS_WITH_ABSTRACT_MEMBER', 12, "'%s' must have a method body because '%s' is not abstract");
 
   /**
+   * 14.1 Imports: If a name <i>N</i> is referenced by a library <i>L</i> and <i>N</i> would be
+   * introduced into the top level scope of <i>L</i> by an import from a library whose URI begins
+   * with <i>dart:</i> and an import from a library whose URI does not begin with <i>dart:</i>:
+   *
+   * * The import from <i>dart:</i> is implicitly extended by a hide N clause.
+   * * A static warning is issued.
+   *
+   *
+   * @param ambiguousName the ambiguous name
+   * @param sdkLibraryName the name of the dart: library that the element is found
+   * @param otherLibraryName the name of the non-dart: library that the element is found
+   */
+  static final StaticWarningCode CONFLICTING_DART_IMPORT = new StaticWarningCode.con1('CONFLICTING_DART_IMPORT', 13, "Element '%s' from SDK library '%s' is implicitly hidden by '%s'");
+
+  /**
    * 7.2 Getters: It is a static warning if a class <i>C</i> declares an instance getter named
    * <i>v</i> and an accessible static member named <i>v</i> or <i>v=</i> is declared in a
    * superclass of <i>C</i>.
    *
    * @param superName the name of the super class declaring a static member
    */
-  static final StaticWarningCode CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER = new StaticWarningCode.con1('CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER', 13, "Superclass '%s' declares static member with the same name");
+  static final StaticWarningCode CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER = new StaticWarningCode.con1('CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER', 14, "Superclass '%s' declares static member with the same name");
 
   /**
    * 7.3 Setters: It is a static warning if a class <i>C</i> declares an instance setter named
@@ -2231,31 +2268,31 @@
    *
    * @param superName the name of the super class declaring a static member
    */
-  static final StaticWarningCode CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER = new StaticWarningCode.con1('CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER', 14, "Superclass '%s' declares static member with the same name");
+  static final StaticWarningCode CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER = new StaticWarningCode.con1('CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER', 15, "Superclass '%s' declares static member with the same name");
 
   /**
    * 7.2 Getters: It is a static warning if a class declares a static getter named <i>v</i> and also
    * has a non-static setter named <i>v=</i>.
    */
-  static final StaticWarningCode CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER = new StaticWarningCode.con1('CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER', 15, "Class '%s' declares non-static setter with the same name");
+  static final StaticWarningCode CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER = new StaticWarningCode.con1('CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER', 16, "Class '%s' declares non-static setter with the same name");
 
   /**
    * 7.3 Setters: It is a static warning if a class declares a static setter named <i>v=</i> and
    * also has a non-static member named <i>v</i>.
    */
-  static final StaticWarningCode CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER = new StaticWarningCode.con1('CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER', 16, "Class '%s' declares non-static member with the same name");
+  static final StaticWarningCode CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER = new StaticWarningCode.con1('CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER', 17, "Class '%s' declares non-static member with the same name");
 
   /**
    * 12.11.2 Const: Given an instance creation expression of the form <i>const q(a<sub>1</sub>,
    * &hellip; a<sub>n</sub>)</i> it is a static warning if <i>q</i> is the constructor of an
    * abstract class but <i>q</i> is not a factory constructor.
    */
-  static final StaticWarningCode CONST_WITH_ABSTRACT_CLASS = new StaticWarningCode.con1('CONST_WITH_ABSTRACT_CLASS', 17, "Abstract classes cannot be created with a 'const' expression");
+  static final StaticWarningCode CONST_WITH_ABSTRACT_CLASS = new StaticWarningCode.con1('CONST_WITH_ABSTRACT_CLASS', 18, "Abstract classes cannot be created with a 'const' expression");
 
   /**
    * 12.7 Maps: It is a static warning if the values of any two keys in a map literal are equal.
    */
-  static final StaticWarningCode EQUAL_KEYS_IN_MAP = new StaticWarningCode.con1('EQUAL_KEYS_IN_MAP', 18, "Keys in a map cannot be equal");
+  static final StaticWarningCode EQUAL_KEYS_IN_MAP = new StaticWarningCode.con1('EQUAL_KEYS_IN_MAP', 19, "Keys in a map cannot be equal");
 
   /**
    * 14.2 Exports: It is a static warning to export two different libraries with the same name.
@@ -2264,7 +2301,7 @@
    * @param uri2 the uri pointing to a second library
    * @param name the shared name of the exported libraries
    */
-  static final StaticWarningCode EXPORT_DUPLICATED_LIBRARY_NAME = new StaticWarningCode.con1('EXPORT_DUPLICATED_LIBRARY_NAME', 19, "The exported libraries '%s' and '%s' should not have the same name '%s'");
+  static final StaticWarningCode EXPORT_DUPLICATED_LIBRARY_NAME = new StaticWarningCode.con1('EXPORT_DUPLICATED_LIBRARY_NAME', 20, "The exported libraries '%s' and '%s' should not have the same name '%s'");
 
   /**
    * 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m &lt; h</i> or if <i>m &gt;
@@ -2274,13 +2311,13 @@
    * @param argumentCount the actual number of positional arguments given
    * @see #NOT_ENOUGH_REQUIRED_ARGUMENTS
    */
-  static final StaticWarningCode EXTRA_POSITIONAL_ARGUMENTS = new StaticWarningCode.con1('EXTRA_POSITIONAL_ARGUMENTS', 20, "%d positional arguments expected, but %d found");
+  static final StaticWarningCode EXTRA_POSITIONAL_ARGUMENTS = new StaticWarningCode.con1('EXTRA_POSITIONAL_ARGUMENTS', 21, "%d positional arguments expected, but %d found");
 
   /**
    * 5. Variables: It is a static warning if a final instance variable that has been initialized at
    * its point of declaration is also initialized in a constructor.
    */
-  static final StaticWarningCode FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION = new StaticWarningCode.con1('FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION', 21, "Values cannot be set in the constructor if they are final, and have already been set");
+  static final StaticWarningCode FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION = new StaticWarningCode.con1('FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION', 22, "Values cannot be set in the constructor if they are final, and have already been set");
 
   /**
    * 5. Variables: It is a static warning if a final instance variable that has been initialized at
@@ -2288,7 +2325,7 @@
    *
    * @param name the name of the field in question
    */
-  static final StaticWarningCode FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR = new StaticWarningCode.con1('FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR', 22, "'%s' is final and was given a value when it was declared, so it cannot be set to a new value");
+  static final StaticWarningCode FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR = new StaticWarningCode.con1('FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR', 23, "'%s' is final and was given a value when it was declared, so it cannot be set to a new value");
 
   /**
    * 7.6.1 Generative Constructors: Execution of an initializer of the form <b>this</b>.<i>v</i> =
@@ -2305,7 +2342,7 @@
    * @param initializerType the name of the type of the initializer expression
    * @param fieldType the name of the type of the field
    */
-  static final StaticWarningCode FIELD_INITIALIZER_NOT_ASSIGNABLE = new StaticWarningCode.con1('FIELD_INITIALIZER_NOT_ASSIGNABLE', 23, "The initializer type '%s' cannot be assigned to the field type '%s'");
+  static final StaticWarningCode FIELD_INITIALIZER_NOT_ASSIGNABLE = new StaticWarningCode.con1('FIELD_INITIALIZER_NOT_ASSIGNABLE', 24, "The initializer type '%s' cannot be assigned to the field type '%s'");
 
   /**
    * 7.6.1 Generative Constructors: An initializing formal has the form <i>this.id</i>. It is a
@@ -2314,7 +2351,7 @@
    * @param parameterType the name of the type of the field formal parameter
    * @param fieldType the name of the type of the field
    */
-  static final StaticWarningCode FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE = new StaticWarningCode.con1('FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE', 24, "The parameter type '%s' is incompatable with the field type '%s'");
+  static final StaticWarningCode FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE = new StaticWarningCode.con1('FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE', 25, "The parameter type '%s' is incompatable with the field type '%s'");
 
   /**
    * 5 Variables: It is a static warning if a library, static or local variable <i>v</i> is final
@@ -2331,7 +2368,13 @@
    *
    * @param name the name of the uninitialized final variable
    */
-  static final StaticWarningCode FINAL_NOT_INITIALIZED = new StaticWarningCode.con1('FINAL_NOT_INITIALIZED', 25, "The final variable '%s' must be initialized");
+  static final StaticWarningCode FINAL_NOT_INITIALIZED = new StaticWarningCode.con1('FINAL_NOT_INITIALIZED', 26, "The final variable '%s' must be initialized");
+
+  /**
+   * 15.5 Function Types: It is a static warning if a concrete class implements Function and does
+   * not have a concrete method named call().
+   */
+  static final StaticWarningCode FUNCTION_WITHOUT_CALL = new StaticWarningCode.con1('FUNCTION_WITHOUT_CALL', 27, "Concrete classes that implement Function must implement the method call()");
 
   /**
    * 14.1 Imports: It is a static warning to import two different libraries with the same name.
@@ -2340,7 +2383,7 @@
    * @param uri2 the uri pointing to a second library
    * @param name the shared name of the imported libraries
    */
-  static final StaticWarningCode IMPORT_DUPLICATED_LIBRARY_NAME = new StaticWarningCode.con1('IMPORT_DUPLICATED_LIBRARY_NAME', 26, "The imported libraries '%s' and '%s' should not have the same name '%s'");
+  static final StaticWarningCode IMPORT_DUPLICATED_LIBRARY_NAME = new StaticWarningCode.con1('IMPORT_DUPLICATED_LIBRARY_NAME', 28, "The imported libraries '%s' and '%s' should not have the same name '%s'");
 
   /**
    * 8.1.1 Inheritance and Overriding: However, if there are multiple members <i>m<sub>1</sub>,
@@ -2352,7 +2395,7 @@
    * not all of the <i>m<sub>i</sub></i> are setters, none of the <i>m<sub>i</sub></i> are
    * inherited, and a static warning is issued.
    */
-  static final StaticWarningCode INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD = new StaticWarningCode.con1('INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD', 27, "'%s' is inherited as a getter and also a method");
+  static final StaticWarningCode INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD = new StaticWarningCode.con1('INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD', 29, "'%s' is inherited as a getter and also a method");
 
   /**
    * 7.1 Instance Methods: It is a static warning if a class <i>C</i> declares an instance method
@@ -2362,7 +2405,7 @@
    * @param memberName the name of the member with the name conflict
    * @param superclassName the name of the enclosing class that has the static member
    */
-  static final StaticWarningCode INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC = new StaticWarningCode.con1('INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC', 28, "'%s' collides with a static member in the superclass '%s'");
+  static final StaticWarningCode INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC = new StaticWarningCode.con1('INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC', 30, "'%s' collides with a static member in the superclass '%s'");
 
   /**
    * 7.2 Getters: It is a static warning if a getter <i>m1</i> overrides a getter <i>m2</i> and the
@@ -2374,7 +2417,7 @@
    * @param className the name of the class where the overridden getter is declared
    * @see #INVALID_METHOD_OVERRIDE_RETURN_TYPE
    */
-  static final StaticWarningCode INVALID_GETTER_OVERRIDE_RETURN_TYPE = new StaticWarningCode.con1('INVALID_GETTER_OVERRIDE_RETURN_TYPE', 29, "The return type '%s' is not assignable to '%s' as required by the getter it is overriding from '%s'");
+  static final StaticWarningCode INVALID_GETTER_OVERRIDE_RETURN_TYPE = new StaticWarningCode.con1('INVALID_GETTER_OVERRIDE_RETURN_TYPE', 31, "The return type '%s' is not assignable to '%s' as required by the getter it is overriding from '%s'");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2385,7 +2428,7 @@
    *          actualParamTypeName
    * @param className the name of the class where the overridden method is declared
    */
-  static final StaticWarningCode INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE', 30, "The parameter type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
+  static final StaticWarningCode INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE', 32, "The parameter type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2397,7 +2440,7 @@
    * @param className the name of the class where the overridden method is declared
    * @see #INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE
    */
-  static final StaticWarningCode INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE', 31, "The parameter type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
+  static final StaticWarningCode INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE', 33, "The parameter type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2408,7 +2451,7 @@
    *          actualParamTypeName
    * @param className the name of the class where the overridden method is declared
    */
-  static final StaticWarningCode INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE', 32, "The parameter type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
+  static final StaticWarningCode INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE', 34, "The parameter type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2420,7 +2463,7 @@
    * @param className the name of the class where the overridden method is declared
    * @see #INVALID_GETTER_OVERRIDE_RETURN_TYPE
    */
-  static final StaticWarningCode INVALID_METHOD_OVERRIDE_RETURN_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_RETURN_TYPE', 33, "The return type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
+  static final StaticWarningCode INVALID_METHOD_OVERRIDE_RETURN_TYPE = new StaticWarningCode.con1('INVALID_METHOD_OVERRIDE_RETURN_TYPE', 35, "The return type '%s' is not assignable to '%s' as required by the method it is overriding from '%s'");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2428,7 +2471,7 @@
    * a formal parameter <i>p</i> and the signature of <i>m1</i> specifies a different default value
    * for <i>p</i>.
    */
-  static final StaticWarningCode INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED = new StaticWarningCode.con1('INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED', 34, "Parameters cannot override default values, this method overrides '%s.%s' where '%s' has a different value");
+  static final StaticWarningCode INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED = new StaticWarningCode.con1('INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED', 36, "Parameters cannot override default values, this method overrides '%s.%s' where '%s' has a different value");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2436,7 +2479,7 @@
    * a formal parameter <i>p</i> and the signature of <i>m1</i> specifies a different default value
    * for <i>p</i>.
    */
-  static final StaticWarningCode INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL = new StaticWarningCode.con1('INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL', 35, "Parameters cannot override default values, this method overrides '%s.%s' where this positional parameter has a different value");
+  static final StaticWarningCode INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL = new StaticWarningCode.con1('INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL', 37, "Parameters cannot override default values, this method overrides '%s.%s' where this positional parameter has a different value");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2446,17 +2489,16 @@
    * @param paramCount the number of named parameters in the overridden member
    * @param className the name of the class from the overridden method
    */
-  static final StaticWarningCode INVALID_OVERRIDE_NAMED = new StaticWarningCode.con1('INVALID_OVERRIDE_NAMED', 36, "Missing the named parameter '%s' to match the overridden method from '%s'");
+  static final StaticWarningCode INVALID_OVERRIDE_NAMED = new StaticWarningCode.con1('INVALID_OVERRIDE_NAMED', 38, "Missing the named parameter '%s' to match the overridden method from '%s'");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
-   * instance member <i>m2</i> and <i>m1</i> has fewer optional positional parameters than
-   * <i>m2</i>.
+   * instance member <i>m2</i> and <i>m1</i> has fewer positional parameters than <i>m2</i>.
    *
    * @param paramCount the number of positional parameters in the overridden member
    * @param className the name of the class from the overridden method
    */
-  static final StaticWarningCode INVALID_OVERRIDE_POSITIONAL = new StaticWarningCode.con1('INVALID_OVERRIDE_POSITIONAL', 37, "Must have at least %d optional parameters to match the overridden method from '%s'");
+  static final StaticWarningCode INVALID_OVERRIDE_POSITIONAL = new StaticWarningCode.con1('INVALID_OVERRIDE_POSITIONAL', 39, "Must have at least %d parameters to match the overridden method from '%s'");
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
@@ -2466,7 +2508,7 @@
    * @param paramCount the number of required parameters in the overridden member
    * @param className the name of the class from the overridden method
    */
-  static final StaticWarningCode INVALID_OVERRIDE_REQUIRED = new StaticWarningCode.con1('INVALID_OVERRIDE_REQUIRED', 38, "Must have %d required parameters or less to match the overridden method from '%s'");
+  static final StaticWarningCode INVALID_OVERRIDE_REQUIRED = new StaticWarningCode.con1('INVALID_OVERRIDE_REQUIRED', 40, "Must have %d required parameters or less to match the overridden method from '%s'");
 
   /**
    * 7.3 Setters: It is a static warning if a setter <i>m1</i> overrides a setter <i>m2</i> and the
@@ -2478,7 +2520,7 @@
    * @param className the name of the class where the overridden setter is declared
    * @see #INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
    */
-  static final StaticWarningCode INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE = new StaticWarningCode.con1('INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE', 39, "The parameter type '%s' is not assignable to '%s' as required by the setter it is overriding from '%s'");
+  static final StaticWarningCode INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE = new StaticWarningCode.con1('INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE', 41, "The parameter type '%s' is not assignable to '%s' as required by the setter it is overriding from '%s'");
 
   /**
    * 12.6 Lists: A run-time list literal &lt;<i>E</i>&gt; [<i>e<sub>1</sub></i> ...
@@ -2494,7 +2536,7 @@
    * It is a static warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 &lt;=
    * j &lt;= m</i>.
    */
-  static final StaticWarningCode LIST_ELEMENT_TYPE_NOT_ASSIGNABLE = new StaticWarningCode.con1('LIST_ELEMENT_TYPE_NOT_ASSIGNABLE', 40, "The element type '%s' cannot be assigned to the list type '%s'");
+  static final StaticWarningCode LIST_ELEMENT_TYPE_NOT_ASSIGNABLE = new StaticWarningCode.con1('LIST_ELEMENT_TYPE_NOT_ASSIGNABLE', 42, "The element type '%s' cannot be assigned to the list type '%s'");
 
   /**
    * 12.7 Map: A run-time map literal &lt;<i>K</i>, <i>V</i>&gt; [<i>k<sub>1</sub></i> :
@@ -2510,7 +2552,7 @@
    * It is a static warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 &lt;=
    * j &lt;= m</i>.
    */
-  static final StaticWarningCode MAP_KEY_TYPE_NOT_ASSIGNABLE = new StaticWarningCode.con1('MAP_KEY_TYPE_NOT_ASSIGNABLE', 41, "The element type '%s' cannot be assigned to the map key type '%s'");
+  static final StaticWarningCode MAP_KEY_TYPE_NOT_ASSIGNABLE = new StaticWarningCode.con1('MAP_KEY_TYPE_NOT_ASSIGNABLE', 43, "The element type '%s' cannot be assigned to the map key type '%s'");
 
   /**
    * 12.7 Map: A run-time map literal &lt;<i>K</i>, <i>V</i>&gt; [<i>k<sub>1</sub></i> :
@@ -2526,20 +2568,20 @@
    * It is a static warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 &lt;=
    * j &lt;= m</i>.
    */
-  static final StaticWarningCode MAP_VALUE_TYPE_NOT_ASSIGNABLE = new StaticWarningCode.con1('MAP_VALUE_TYPE_NOT_ASSIGNABLE', 42, "The element type '%s' cannot be assigned to the map value type '%s'");
+  static final StaticWarningCode MAP_VALUE_TYPE_NOT_ASSIGNABLE = new StaticWarningCode.con1('MAP_VALUE_TYPE_NOT_ASSIGNABLE', 44, "The element type '%s' cannot be assigned to the map value type '%s'");
 
   /**
    * 7.3 Setters: It is a static warning if a class has a setter named <i>v=</i> with argument type
    * <i>T</i> and a getter named <i>v</i> with return type <i>S</i>, and <i>T</i> may not be
    * assigned to <i>S</i>.
    */
-  static final StaticWarningCode MISMATCHED_GETTER_AND_SETTER_TYPES = new StaticWarningCode.con1('MISMATCHED_GETTER_AND_SETTER_TYPES', 43, "The parameter type for setter '%s' is '%s' which is not assignable to its getter (of type '%s')");
+  static final StaticWarningCode MISMATCHED_GETTER_AND_SETTER_TYPES = new StaticWarningCode.con1('MISMATCHED_GETTER_AND_SETTER_TYPES', 45, "The parameter type for setter '%s' is '%s' which is not assignable to its getter (of type '%s')");
 
   /**
    * 12.11.1 New: It is a static warning if <i>q</i> is a constructor of an abstract class and
    * <i>q</i> is not a factory constructor.
    */
-  static final StaticWarningCode NEW_WITH_ABSTRACT_CLASS = new StaticWarningCode.con1('NEW_WITH_ABSTRACT_CLASS', 44, "Abstract classes cannot be created with a 'new' expression");
+  static final StaticWarningCode NEW_WITH_ABSTRACT_CLASS = new StaticWarningCode.con1('NEW_WITH_ABSTRACT_CLASS', 46, "Abstract classes cannot be created with a 'new' expression");
 
   /**
    * 15.8 Parameterized Types: Any use of a malbounded type gives rise to a static warning.
@@ -2550,7 +2592,7 @@
    * @see CompileTimeErrorCode#CONST_WITH_INVALID_TYPE_PARAMETERS
    * @see StaticTypeWarningCode#WRONG_NUMBER_OF_TYPE_ARGUMENTS
    */
-  static final StaticWarningCode NEW_WITH_INVALID_TYPE_PARAMETERS = new StaticWarningCode.con1('NEW_WITH_INVALID_TYPE_PARAMETERS', 45, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
+  static final StaticWarningCode NEW_WITH_INVALID_TYPE_PARAMETERS = new StaticWarningCode.con1('NEW_WITH_INVALID_TYPE_PARAMETERS', 47, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
 
   /**
    * 12.11.1 New: It is a static warning if <i>T</i> is not a class accessible in the current scope,
@@ -2558,7 +2600,7 @@
    *
    * @param name the name of the non-type element
    */
-  static final StaticWarningCode NEW_WITH_NON_TYPE = new StaticWarningCode.con1('NEW_WITH_NON_TYPE', 46, "The name '%s' is not a class");
+  static final StaticWarningCode NEW_WITH_NON_TYPE = new StaticWarningCode.con1('NEW_WITH_NON_TYPE', 48, "The name '%s' is not a class");
 
   /**
    * 12.11.1 New: If <i>T</i> is a class or parameterized type accessible in the current scope then:
@@ -2569,7 +2611,7 @@
    * a<sub>n+1</sub>, &hellip; x<sub>n+k</sub>: a<sub>n+kM/sub>)</i> it is a static warning if the
    * type <i>T</i> does not declare a constructor with the same name as the declaration of <i>T</i>.
    */
-  static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR = new StaticWarningCode.con1('NEW_WITH_UNDEFINED_CONSTRUCTOR', 47, "The class '%s' does not have a constructor '%s'");
+  static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR = new StaticWarningCode.con1('NEW_WITH_UNDEFINED_CONSTRUCTOR', 49, "The class '%s' does not have a constructor '%s'");
 
   /**
    * 12.11.1 New: If <i>T</i> is a class or parameterized type accessible in the current scope then:
@@ -2580,7 +2622,7 @@
    * a<sub>n+1</sub>, &hellip; x<sub>n+k</sub>: a<sub>n+kM/sub>)</i> it is a static warning if the
    * type <i>T</i> does not declare a constructor with the same name as the declaration of <i>T</i>.
    */
-  static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT = new StaticWarningCode.con1('NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT', 48, "The class '%s' does not have a default constructor");
+  static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT = new StaticWarningCode.con1('NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT', 50, "The class '%s' does not have a default constructor");
 
   /**
    * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
@@ -2600,7 +2642,7 @@
    * @param memberName the name of the fourth member
    * @param additionalCount the number of additional missing members that aren't listed
    */
-  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS', 49, "Missing inherited members: '%s', '%s', '%s', '%s' and %d more");
+  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS', 51, "Missing inherited members: '%s', '%s', '%s', '%s' and %d more");
 
   /**
    * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
@@ -2619,7 +2661,7 @@
    * @param memberName the name of the third member
    * @param memberName the name of the fourth member
    */
-  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR', 50, "Missing inherited members: '%s', '%s', '%s' and '%s'");
+  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR', 52, "Missing inherited members: '%s', '%s', '%s' and '%s'");
 
   /**
    * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
@@ -2635,7 +2677,7 @@
    *
    * @param memberName the name of the member
    */
-  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE', 51, "Missing inherited member '%s'");
+  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE', 53, "Missing inherited member '%s'");
 
   /**
    * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
@@ -2653,7 +2695,7 @@
    * @param memberName the name of the second member
    * @param memberName the name of the third member
    */
-  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE', 52, "Missing inherited members: '%s', '%s' and '%s'");
+  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE', 54, "Missing inherited members: '%s', '%s' and '%s'");
 
   /**
    * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
@@ -2670,7 +2712,7 @@
    * @param memberName the name of the first member
    * @param memberName the name of the second member
    */
-  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO', 53, "Missing inherited members: '%s' and '%s'");
+  static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO = new StaticWarningCode.con1('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO', 55, "Missing inherited members: '%s' and '%s'");
 
   /**
    * 13.11 Try: An on-catch clause of the form <i>on T catch (p<sub>1</sub>, p<sub>2</sub>) s</i> or
@@ -2680,18 +2722,18 @@
    *
    * @param name the name of the non-type element
    */
-  static final StaticWarningCode NON_TYPE_IN_CATCH_CLAUSE = new StaticWarningCode.con1('NON_TYPE_IN_CATCH_CLAUSE', 54, "The name '%s' is not a type and cannot be used in an on-catch clause");
+  static final StaticWarningCode NON_TYPE_IN_CATCH_CLAUSE = new StaticWarningCode.con1('NON_TYPE_IN_CATCH_CLAUSE', 56, "The name '%s' is not a type and cannot be used in an on-catch clause");
 
   /**
    * 7.1.1 Operators: It is a static warning if the return type of the user-declared operator []= is
    * explicitly declared and not void.
    */
-  static final StaticWarningCode NON_VOID_RETURN_FOR_OPERATOR = new StaticWarningCode.con1('NON_VOID_RETURN_FOR_OPERATOR', 55, "The return type of the operator []= must be 'void'");
+  static final StaticWarningCode NON_VOID_RETURN_FOR_OPERATOR = new StaticWarningCode.con1('NON_VOID_RETURN_FOR_OPERATOR', 57, "The return type of the operator []= must be 'void'");
 
   /**
    * 7.3 Setters: It is a static warning if a setter declares a return type other than void.
    */
-  static final StaticWarningCode NON_VOID_RETURN_FOR_SETTER = new StaticWarningCode.con1('NON_VOID_RETURN_FOR_SETTER', 56, "The return type of the setter must be 'void'");
+  static final StaticWarningCode NON_VOID_RETURN_FOR_SETTER = new StaticWarningCode.con1('NON_VOID_RETURN_FOR_SETTER', 58, "The return type of the setter must be 'void'");
 
   /**
    * 15.1 Static Types: A type <i>T</i> is malformed iff: * <i>T</i> has the form <i>id</i> or the
@@ -2705,7 +2747,7 @@
    *
    * @param nonTypeName the name that is not a type
    */
-  static final StaticWarningCode NOT_A_TYPE = new StaticWarningCode.con1('NOT_A_TYPE', 57, "%s is not a type");
+  static final StaticWarningCode NOT_A_TYPE = new StaticWarningCode.con1('NOT_A_TYPE', 59, "%s is not a type");
 
   /**
    * 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m &lt; h</i> or if <i>m &gt;
@@ -2715,7 +2757,7 @@
    * @param argumentCount the actual number of positional arguments given
    * @see #EXTRA_POSITIONAL_ARGUMENTS
    */
-  static final StaticWarningCode NOT_ENOUGH_REQUIRED_ARGUMENTS = new StaticWarningCode.con1('NOT_ENOUGH_REQUIRED_ARGUMENTS', 58, "%d required argument(s) expected, but %d found");
+  static final StaticWarningCode NOT_ENOUGH_REQUIRED_ARGUMENTS = new StaticWarningCode.con1('NOT_ENOUGH_REQUIRED_ARGUMENTS', 60, "%d required argument(s) expected, but %d found");
 
   /**
    * 14.3 Parts: It is a static warning if the referenced part declaration <i>p</i> names a library
@@ -2724,7 +2766,7 @@
    * @param expectedLibraryName the name of expected library name
    * @param actualLibraryName the non-matching actual library name from the "part of" declaration
    */
-  static final StaticWarningCode PART_OF_DIFFERENT_LIBRARY = new StaticWarningCode.con1('PART_OF_DIFFERENT_LIBRARY', 59, "Expected this library to be part of '%s', not '%s'");
+  static final StaticWarningCode PART_OF_DIFFERENT_LIBRARY = new StaticWarningCode.con1('PART_OF_DIFFERENT_LIBRARY', 61, "Expected this library to be part of '%s', not '%s'");
 
   /**
    * 7.6.2 Factories: It is a static warning if the function type of <i>k'</i> is not a subtype of
@@ -2733,7 +2775,7 @@
    * @param redirectedName the name of the redirected constructor
    * @param redirectingName the name of the redirecting constructor
    */
-  static final StaticWarningCode REDIRECT_TO_INVALID_FUNCTION_TYPE = new StaticWarningCode.con1('REDIRECT_TO_INVALID_FUNCTION_TYPE', 60, "The redirected constructor '%s' has incompatible parameters with '%s'");
+  static final StaticWarningCode REDIRECT_TO_INVALID_FUNCTION_TYPE = new StaticWarningCode.con1('REDIRECT_TO_INVALID_FUNCTION_TYPE', 62, "The redirected constructor '%s' has incompatible parameters with '%s'");
 
   /**
    * 7.6.2 Factories: It is a static warning if the function type of <i>k'</i> is not a subtype of
@@ -2742,21 +2784,21 @@
    * @param redirectedName the name of the redirected constructor return type
    * @param redirectingName the name of the redirecting constructor return type
    */
-  static final StaticWarningCode REDIRECT_TO_INVALID_RETURN_TYPE = new StaticWarningCode.con1('REDIRECT_TO_INVALID_RETURN_TYPE', 61, "The return type '%s' of the redirected constructor is not a subclass of '%s'");
+  static final StaticWarningCode REDIRECT_TO_INVALID_RETURN_TYPE = new StaticWarningCode.con1('REDIRECT_TO_INVALID_RETURN_TYPE', 63, "The return type '%s' of the redirected constructor is not assignable to '%s'");
 
   /**
    * 7.6.2 Factories: It is a static warning if type does not denote a class accessible in the
    * current scope; if type does denote such a class <i>C</i> it is a static warning if the
    * referenced constructor (be it <i>type</i> or <i>type.id</i>) is not a constructor of <i>C</i>.
    */
-  static final StaticWarningCode REDIRECT_TO_MISSING_CONSTRUCTOR = new StaticWarningCode.con1('REDIRECT_TO_MISSING_CONSTRUCTOR', 62, "The constructor '%s' could not be found in '%s'");
+  static final StaticWarningCode REDIRECT_TO_MISSING_CONSTRUCTOR = new StaticWarningCode.con1('REDIRECT_TO_MISSING_CONSTRUCTOR', 64, "The constructor '%s' could not be found in '%s'");
 
   /**
    * 7.6.2 Factories: It is a static warning if type does not denote a class accessible in the
    * current scope; if type does denote such a class <i>C</i> it is a static warning if the
    * referenced constructor (be it <i>type</i> or <i>type.id</i>) is not a constructor of <i>C</i>.
    */
-  static final StaticWarningCode REDIRECT_TO_NON_CLASS = new StaticWarningCode.con1('REDIRECT_TO_NON_CLASS', 63, "The name '%s' is not a type and cannot be used in a redirected constructor");
+  static final StaticWarningCode REDIRECT_TO_NON_CLASS = new StaticWarningCode.con1('REDIRECT_TO_NON_CLASS', 65, "The name '%s' is not a type and cannot be used in a redirected constructor");
 
   /**
    * 13.11 Return: Let <i>f</i> be the function immediately enclosing a return statement of the form
@@ -2766,7 +2808,7 @@
    * * The return type of <i>f</i> may not be assigned to void.
    * </ol>
    */
-  static final StaticWarningCode RETURN_WITHOUT_VALUE = new StaticWarningCode.con1('RETURN_WITHOUT_VALUE', 64, "Missing return value after 'return'");
+  static final StaticWarningCode RETURN_WITHOUT_VALUE = new StaticWarningCode.con1('RETURN_WITHOUT_VALUE', 66, "Missing return value after 'return'");
 
   /**
    * 12.15.3 Static Invocation: It is a static warning if <i>C</i> does not declare a static method
@@ -2774,19 +2816,19 @@
    *
    * @param memberName the name of the instance member
    */
-  static final StaticWarningCode STATIC_ACCESS_TO_INSTANCE_MEMBER = new StaticWarningCode.con1('STATIC_ACCESS_TO_INSTANCE_MEMBER', 65, "Instance member '%s' cannot be accessed using static access");
+  static final StaticWarningCode STATIC_ACCESS_TO_INSTANCE_MEMBER = new StaticWarningCode.con1('STATIC_ACCESS_TO_INSTANCE_MEMBER', 67, "Instance member '%s' cannot be accessed using static access");
 
   /**
    * 13.9 Switch: It is a static warning if the type of <i>e</i> may not be assigned to the type of
    * <i>e<sub>k</sub></i>.
    */
-  static final StaticWarningCode SWITCH_EXPRESSION_NOT_ASSIGNABLE = new StaticWarningCode.con1('SWITCH_EXPRESSION_NOT_ASSIGNABLE', 66, "Type '%s' of the switch expression is not assignable to the type '%s' of case expressions");
+  static final StaticWarningCode SWITCH_EXPRESSION_NOT_ASSIGNABLE = new StaticWarningCode.con1('SWITCH_EXPRESSION_NOT_ASSIGNABLE', 68, "Type '%s' of the switch expression is not assignable to the type '%s' of case expressions");
 
   /**
    * 12.31 Type Test: It is a static warning if <i>T</i> does not denote a type available in the
    * current lexical scope.
    */
-  static final StaticWarningCode TYPE_TEST_NON_TYPE = new StaticWarningCode.con1('TYPE_TEST_NON_TYPE', 67, "The name '%s' is not a type and cannot be used in an 'is' expression");
+  static final StaticWarningCode TYPE_TEST_NON_TYPE = new StaticWarningCode.con1('TYPE_TEST_NON_TYPE', 69, "The name '%s' is not a type and cannot be used in an 'is' expression");
 
   /**
    * 10 Generics: However, a type parameter is considered to be a malformed type when referenced by
@@ -2795,7 +2837,7 @@
    * 15.1 Static Types: Any use of a malformed type gives rise to a static warning. A malformed type
    * is then interpreted as dynamic by the static type checker and the runtime.
    */
-  static final StaticWarningCode TYPE_PARAMETER_REFERENCED_BY_STATIC = new StaticWarningCode.con1('TYPE_PARAMETER_REFERENCED_BY_STATIC', 68, "Static members cannot reference type parameters");
+  static final StaticWarningCode TYPE_PARAMETER_REFERENCED_BY_STATIC = new StaticWarningCode.con1('TYPE_PARAMETER_REFERENCED_BY_STATIC', 70, "Static members cannot reference type parameters");
 
   /**
    * 12.15.3 Static Invocation: A static method invocation <i>i</i> has the form
@@ -2805,12 +2847,12 @@
    *
    * @param undefinedClassName the name of the undefined class
    */
-  static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode.con1('UNDEFINED_CLASS', 69, "Undefined class '%s'");
+  static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode.con1('UNDEFINED_CLASS', 71, "Undefined class '%s'");
 
   /**
    * Same as [UNDEFINED_CLASS], but to catch using "boolean" instead of "bool".
    */
-  static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode.con1('UNDEFINED_CLASS_BOOLEAN', 70, "Undefined class 'boolean'; did you mean 'bool'?");
+  static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode.con1('UNDEFINED_CLASS_BOOLEAN', 72, "Undefined class 'boolean'; did you mean 'bool'?");
 
   /**
    * 12.17 Getter Invocation: It is a static warning if there is no class <i>C</i> in the enclosing
@@ -2820,7 +2862,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 StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode.con1('UNDEFINED_GETTER', 71, "There is no such getter '%s' in '%s'");
+  static final StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode.con1('UNDEFINED_GETTER', 73, "There is no such getter '%s' in '%s'");
 
   /**
    * 12.30 Identifier Reference: It is as static warning if an identifier expression of the form
@@ -2830,7 +2872,7 @@
    *
    * @param name the name of the identifier
    */
-  static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode.con1('UNDEFINED_IDENTIFIER', 72, "Undefined name '%s'");
+  static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode.con1('UNDEFINED_IDENTIFIER', 74, "Undefined name '%s'");
 
   /**
    * 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>, <i>1<=i<=l</i>,
@@ -2839,7 +2881,7 @@
    *
    * @param name the name of the requested named parameter
    */
-  static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode.con1('UNDEFINED_NAMED_PARAMETER', 73, "The named parameter '%s' is not defined");
+  static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode.con1('UNDEFINED_NAMED_PARAMETER', 75, "The named parameter '%s' is not defined");
 
   /**
    * 12.18 Assignment: It is as static warning if an assignment of the form <i>v = e</i> occurs
@@ -2854,7 +2896,7 @@
    * @param setterName the name of the getter
    * @param enclosingType the name of the enclosing type where the setter is being looked for
    */
-  static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode.con1('UNDEFINED_SETTER', 74, "There is no such setter '%s' in '%s'");
+  static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode.con1('UNDEFINED_SETTER', 76, "There is no such setter '%s' in '%s'");
 
   /**
    * 12.15.3 Static Invocation: It is a static warning if <i>C</i> does not declare a static method
@@ -2863,7 +2905,7 @@
    * @param methodName the name of the method
    * @param enclosingType the name of the enclosing type where the method is being looked for
    */
-  static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode.con1('UNDEFINED_STATIC_METHOD_OR_GETTER', 75, "There is no such static method '%s' in '%s'");
+  static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode.con1('UNDEFINED_STATIC_METHOD_OR_GETTER', 77, "There is no such static method '%s' in '%s'");
   static final List<StaticWarningCode> values = [
       AMBIGUOUS_IMPORT,
       ARGUMENT_TYPE_NOT_ASSIGNABLE,
@@ -2878,6 +2920,7 @@
       COMMENT_REFERENCE_UNDECLARED_IDENTIFIER,
       COMMENT_REFERENCE_URI_NOT_LIBRARY,
       CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
+      CONFLICTING_DART_IMPORT,
       CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER,
       CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER,
       CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER,
@@ -2891,6 +2934,7 @@
       FIELD_INITIALIZER_NOT_ASSIGNABLE,
       FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
       FINAL_NOT_INITIALIZED,
+      FUNCTION_WITHOUT_CALL,
       IMPORT_DUPLICATED_LIBRARY_NAME,
       INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD,
       INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC,
@@ -3074,12 +3118,28 @@
 class StaticTypeWarningCode extends Enum<StaticTypeWarningCode> implements ErrorCode {
 
   /**
+   * 12.7 Lists: A fresh instance (7.6.1) <i>a</i>, of size <i>n</i>, whose class implements the
+   * built-in class <i>List&lt;E></i> is allocated.
+   *
+   * @param numTypeArgument the number of provided type arguments
+   */
+  static final StaticTypeWarningCode EXPECTED_ONE_LIST_TYPE_ARGUMENTS = new StaticTypeWarningCode.con1('EXPECTED_ONE_LIST_TYPE_ARGUMENTS', 0, "List literal requires exactly one type arguments or none, but %d found");
+
+  /**
+   * 12.8 Maps: A fresh instance (7.6.1) <i>m</i>, of size <i>n</i>, whose class implements the
+   * built-in class <i>Map&lt;K, V></i> is allocated.
+   *
+   * @param numTypeArgument the number of provided type arguments
+   */
+  static final StaticTypeWarningCode EXPECTED_TWO_MAP_TYPE_ARGUMENTS = new StaticTypeWarningCode.con1('EXPECTED_TWO_MAP_TYPE_ARGUMENTS', 1, "Map literal requires exactly two type arguments or none, but %d found");
+
+  /**
    * 12.18 Assignment: Let <i>T</i> be the static type of <i>e<sub>1</sub></i>. It is a static type
    * warning if <i>T</i> does not have an accessible instance setter named <i>v=</i>.
    *
    * @see #UNDEFINED_SETTER
    */
-  static final StaticTypeWarningCode INACCESSIBLE_SETTER = new StaticTypeWarningCode.con1('INACCESSIBLE_SETTER', 0, "");
+  static final StaticTypeWarningCode INACCESSIBLE_SETTER = new StaticTypeWarningCode.con1('INACCESSIBLE_SETTER', 2, "");
 
   /**
    * 8.1.1 Inheritance and Overriding: However, if there are multiple members <i>m<sub>1</sub>,
@@ -3101,7 +3161,7 @@
    * * Otherwise none of the members <i>m<sub>1</sub>, &hellip;, m<sub>k</sub></i> is inherited.
    * </ol>
    */
-  static final StaticTypeWarningCode INCONSISTENT_METHOD_INHERITANCE = new StaticTypeWarningCode.con1('INCONSISTENT_METHOD_INHERITANCE', 1, "'%s' is inherited by at least two interfaces inconsistently");
+  static final StaticTypeWarningCode INCONSISTENT_METHOD_INHERITANCE = new StaticTypeWarningCode.con1('INCONSISTENT_METHOD_INHERITANCE', 3, "'%s' is inherited by at least two interfaces inconsistently");
 
   /**
    * 12.15.1 Ordinary Invocation: It is a static type warning if <i>T</i> does not have an
@@ -3110,7 +3170,7 @@
    * @param memberName the name of the static member
    * @see UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
    */
-  static final StaticTypeWarningCode INSTANCE_ACCESS_TO_STATIC_MEMBER = new StaticTypeWarningCode.con1('INSTANCE_ACCESS_TO_STATIC_MEMBER', 2, "Static member '%s' cannot be accessed using instance access");
+  static final StaticTypeWarningCode INSTANCE_ACCESS_TO_STATIC_MEMBER = new StaticTypeWarningCode.con1('INSTANCE_ACCESS_TO_STATIC_MEMBER', 4, "Static member '%s' cannot be accessed using instance access");
 
   /**
    * 12.18 Assignment: It is a static type warning if the static type of <i>e</i> may not be
@@ -3127,7 +3187,7 @@
    * @param rhsTypeName the name of the right hand side type
    * @param lhsTypeName the name of the left hand side type
    */
-  static final StaticTypeWarningCode INVALID_ASSIGNMENT = new StaticTypeWarningCode.con1('INVALID_ASSIGNMENT', 3, "A value of type '%s' cannot be assigned to a variable of type '%s'");
+  static final StaticTypeWarningCode INVALID_ASSIGNMENT = new StaticTypeWarningCode.con1('INVALID_ASSIGNMENT', 5, "A value of type '%s' cannot be assigned to a variable of type '%s'");
 
   /**
    * 12.15.1 Ordinary Invocation: An ordinary method invocation <i>i</i> has the form
@@ -3149,7 +3209,7 @@
    *
    * @param nonFunctionIdentifier the name of the identifier that is not a function type
    */
-  static final StaticTypeWarningCode INVOCATION_OF_NON_FUNCTION = new StaticTypeWarningCode.con1('INVOCATION_OF_NON_FUNCTION', 4, "'%s' is not a method");
+  static final StaticTypeWarningCode INVOCATION_OF_NON_FUNCTION = new StaticTypeWarningCode.con1('INVOCATION_OF_NON_FUNCTION', 6, "'%s' is not a method");
 
   /**
    * 12.14.4 Function Expression Invocation: A function expression invocation <i>i</i> has the form
@@ -3159,7 +3219,7 @@
    * It is a static type warning if the static type <i>F</i> of <i>e<sub>f</sub></i> may not be
    * assigned to a function type.
    */
-  static final StaticTypeWarningCode INVOCATION_OF_NON_FUNCTION_EXPRESSION = new StaticTypeWarningCode.con1('INVOCATION_OF_NON_FUNCTION_EXPRESSION', 5, "Cannot invoke a non-function");
+  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
@@ -3172,19 +3232,19 @@
    *
    * 13.8 Do: It is a static type warning if the type of <i>e</i> cannot be assigned to bool.
    */
-  static final StaticTypeWarningCode NON_BOOL_CONDITION = new StaticTypeWarningCode.con1('NON_BOOL_CONDITION', 6, "Conditions must have a static type of 'bool'");
+  static final StaticTypeWarningCode NON_BOOL_CONDITION = new StaticTypeWarningCode.con1('NON_BOOL_CONDITION', 8, "Conditions must have a static type of 'bool'");
 
   /**
    * 13.15 Assert: It is a static type warning if the type of <i>e</i> may not be assigned to either
    * bool or () &rarr; bool
    */
-  static final StaticTypeWarningCode NON_BOOL_EXPRESSION = new StaticTypeWarningCode.con1('NON_BOOL_EXPRESSION', 7, "Assertions must be on either a 'bool' or '() -> bool'");
+  static final StaticTypeWarningCode NON_BOOL_EXPRESSION = new StaticTypeWarningCode.con1('NON_BOOL_EXPRESSION', 9, "Assertions must be on either a 'bool' or '() -> 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', 8, "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', 10, "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
@@ -3194,7 +3254,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', 9, "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', 11, "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
@@ -3202,8 +3262,6 @@
    * expression are not subtypes of the bounds of the corresponding formal type parameters of
    * <i>G</i>.
    *
-   * 10 Generics: It is a static type warning if a type parameter is a supertype of its upper bound.
-   *
    * 15.8 Parameterized Types: If <i>S</i> is the static type of a member <i>m</i> of <i>G</i>, then
    * the static type of the member <i>m</i> of <i>G&lt;A<sub>1</sub>, &hellip; A<sub>n</sub>&gt;</i>
    * is <i>[A<sub>1</sub>, &hellip;, A<sub>n</sub>/T<sub>1</sub>, &hellip;, T<sub>n</sub>]S</i>
@@ -3218,8 +3276,17 @@
    * @param boundedTypeName the name of the type used in the instance creation that should be
    *          limited by the bound as specified in the class declaration
    * @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', 10, "'%s' does not extend '%s'");
+  static final StaticTypeWarningCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new StaticTypeWarningCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 12, "'%s' does not extend '%s'");
+
+  /**
+   * 10 Generics: It is a static type warning if a type parameter is a supertype of its upper bound.
+   *
+   * @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");
 
   /**
    * 12.17 Getter Invocation: Let <i>T</i> be the static type of <i>e</i>. It is a static type
@@ -3228,7 +3295,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', 11, "There is no such getter '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_GETTER = new StaticTypeWarningCode.con1('UNDEFINED_GETTER', 14, "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
@@ -3237,7 +3304,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', 12, "The method '%s' is not defined for the class '%s'");
+  static final StaticTypeWarningCode UNDEFINED_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_METHOD', 15, "The method '%s' is not defined for the class '%s'");
 
   /**
    * 12.18 Assignment: Evaluation of an assignment of the form
@@ -3255,7 +3322,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', 13, "There is no such operator '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_OPERATOR = new StaticTypeWarningCode.con1('UNDEFINED_OPERATOR', 16, "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
@@ -3265,7 +3332,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', 14, "There is no such setter '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_SETTER = new StaticTypeWarningCode.con1('UNDEFINED_SETTER', 17, "There is no such setter '%s' in '%s'");
 
   /**
    * 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -3276,7 +3343,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', 15, "There is no such method '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_SUPER_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_SUPER_METHOD', 18, "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
@@ -3286,7 +3353,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', 16, "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', 19, "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
@@ -3298,8 +3365,10 @@
    * @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', 17, "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', 20, "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,
       INACCESSIBLE_SETTER,
       INCONSISTENT_METHOD_INHERITANCE,
       INSTANCE_ACCESS_TO_STATIC_MEMBER,
@@ -3311,6 +3380,7 @@
       NON_TYPE_AS_TYPE_ARGUMENT,
       RETURN_OF_INVALID_TYPE,
       TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+      TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
       UNDEFINED_GETTER,
       UNDEFINED_METHOD,
       UNDEFINED_OPERATOR,
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_core.dart b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
index 5baaf06..64ef68a 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_core.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
@@ -1,7 +1,6 @@
 library java.core;
 
 import "dart:math" as math;
-import "dart:collection" show ListBase;
 
 class JavaSystem {
   static int currentTimeMillis() {
@@ -164,6 +163,7 @@
     return fmt.replaceAllMapped(new RegExp(r'%(.)'), (match) {
       switch (match.group(1)) {
         case '%': return '%';
+        case 'd':
         case 's':
           if (index >= args.length) {
             throw new MissingFormatArgumentException(match.group(0));
@@ -329,110 +329,6 @@
   MissingFormatArgumentException(this.s);
 }
 
-class ListWrapper<E> extends ListBase<E> implements List<E> {
-  List<E> elements = new List<E>();
-
-  Iterator<E> get iterator {
-    return elements.iterator;
-  }
-
-  E operator [](int index) {
-    return elements[index];
-  }
-
-  void operator []=(int index, E value) {
-    elements[index] = value;
-  }
-
-  void set length(int newLength) {
-    elements.length = newLength;
-  }
-
-  int get length => elements.length;
-
-  void add(E value) {
-    elements.add(value);
-  }
-
-  void addLast(E value) {
-    elements.add(value);
-  }
-
-  void addAll(Iterable<E> iterable) {
-    elements.addAll(iterable);
-  }
-
-  void setAll(int index, Iterable<E> iterable) {
-    elements.setAll(index, iterable);
-  }
-
-  void sort([int compare(E a, E b)]) {
-    elements.sort(compare);
-  }
-
-  void shuffle([math.Random random]) {
-    elements.shuffle(random);
-  }
-
-  int indexOf(E element, [int start = 0]) {
-    return elements.indexOf(element, start);
-  }
-
-  void insert(int index, E element) {
-    elements.insert(index, element);
-  }
-
-  void insertAll(int index, Iterable<E> iterable) {
-    elements.insertAll(index, iterable);
-  }
-
-  int lastIndexOf(E element, [int start]) {
-    return elements.lastIndexOf(element, start);
-  }
-
-  void clear() {
-    elements.clear();
-  }
-
-  bool remove(Object element) {
-    return elements.remove(element);
-  }
-
-  E removeAt(int index) {
-    return elements.removeAt(index);
-  }
-
-  E removeLast() {
-    return elements.removeLast();
-  }
-
-  Iterable<E> get reversed => elements.reversed;
-
-  List<E> sublist(int start, [int end]) => elements.sublist(start, end);
-
-  List<E> getRange(int start, int length) => sublist(start, start + length);
-
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
-    elements.setRange(start, end, iterable, skipCount);
-  }
-
-  void removeRange(int start, int end) {
-    elements.removeRange(start, end);
-  }
-
-  void replaceRange(int start, int end, Iterable<E> iterable) {
-    elements.replaceRange(start, end, iterable);
-  }
-
-  void fillRange(int start, int end, [E fillValue]) {
-    elements.fillRange(start, end, fillValue);
-  }
-
-  Map<int, E> asMap() {
-    return elements.asMap();
-  }
-}
-
 class JavaIterator<E> {
   Iterable<E> _iterable;
   List<E> _elements = new List<E>();
@@ -492,6 +388,12 @@
   return result;
 }
 
+javaListSet(List list, int index, newValue) {
+  var oldValue = list[index];
+  list[index] = newValue;
+  return oldValue;
+}
+
 bool javaSetAdd(Set s, o) {
   if (!s.contains(o)) {
     s.add(o);
diff --git a/pkg/analyzer_experimental/lib/src/generated/parser.dart b/pkg/analyzer_experimental/lib/src/generated/parser.dart
index 26185b6..9a92aba 100644
--- a/pkg/analyzer_experimental/lib/src/generated/parser.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/parser.dart
@@ -205,7 +205,7 @@
       gatherTodoComments(token);
       return compilationUnit;
     } finally {
-      instrumentation.log();
+      instrumentation.log2(2);
     }
   }
 
@@ -1368,7 +1368,8 @@
    *
    * <pre>
    * classDeclaration ::=
-   *     metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}'
+   *     metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' |
+   *     metadata 'abstract'? 'class' mixinApplicationClass
    * </pre>
    *
    * @param commentAndMetadata the metadata to be associated with the member
@@ -1376,8 +1377,19 @@
    *          not given
    * @return the class declaration that was parsed
    */
-  ClassDeclaration parseClassDeclaration(CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
+  CompilationUnitMember parseClassDeclaration(CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
     Token keyword = expect(Keyword.CLASS);
+    if (matchesIdentifier()) {
+      Token next = peek();
+      if (matches4(next, TokenType.LT)) {
+        next = skipTypeParameterList(next);
+        if (next != null && matches4(next, TokenType.EQ)) {
+          return parseClassTypeAlias(commentAndMetadata, keyword);
+        }
+      } else if (matches4(next, TokenType.EQ)) {
+        return parseClassTypeAlias(commentAndMetadata, keyword);
+      }
+    }
     SimpleIdentifier name = parseSimpleIdentifier();
     String className = name.name;
     TypeParameterList typeParameters = null;
@@ -3187,12 +3199,6 @@
    * @return the list literal that was parsed
    */
   ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
-    if (typeArguments != null) {
-      int num = typeArguments.arguments.length;
-      if (num != 1) {
-        reportError(ParserErrorCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, typeArguments, [num]);
-      }
-    }
     if (matches5(TokenType.INDEX)) {
       BeginToken leftBracket = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, _currentToken.offset);
       Token rightBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1);
@@ -3299,12 +3305,6 @@
    * @return the map literal that was parsed
    */
   MapLiteral parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
-    if (typeArguments != null) {
-      int num = typeArguments.arguments.length;
-      if (num != 2) {
-        reportError(ParserErrorCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, typeArguments, [num]);
-      }
-    }
     Token leftBracket = expect2(TokenType.OPEN_CURLY_BRACKET);
     List<MapLiteralEntry> entries = new List<MapLiteralEntry>();
     if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
@@ -4501,10 +4501,12 @@
       if (matches4(next, TokenType.LT)) {
         next = skipTypeParameterList(next);
         if (next != null && matches4(next, TokenType.EQ)) {
-          return parseClassTypeAlias(commentAndMetadata, keyword);
+          TypeAlias typeAlias = parseClassTypeAlias(commentAndMetadata, keyword);
+          return typeAlias;
         }
       } else if (matches4(next, TokenType.EQ)) {
-        return parseClassTypeAlias(commentAndMetadata, keyword);
+        TypeAlias typeAlias = parseClassTypeAlias(commentAndMetadata, keyword);
+        return typeAlias;
       }
     }
     return parseFunctionTypeAlias(commentAndMetadata, keyword);
@@ -5691,118 +5693,117 @@
   static final ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = new ParserErrorCode.con3('CONTINUE_OUTSIDE_OF_LOOP', 18, "A continue statement cannot be used outside of a loop or switch statement");
   static final ParserErrorCode CONTINUE_WITHOUT_LABEL_IN_CASE = new ParserErrorCode.con3('CONTINUE_WITHOUT_LABEL_IN_CASE', 19, "A continue statement in a switch statement must have a label as a target");
   static final ParserErrorCode DEPRECATED_ARGUMENT_DEFINITION_TEST = new ParserErrorCode.con3('DEPRECATED_ARGUMENT_DEFINITION_TEST', 20, "The argument definition test ('?' operator) has been deprecated");
-  static final ParserErrorCode DIRECTIVE_AFTER_DECLARATION = new ParserErrorCode.con3('DIRECTIVE_AFTER_DECLARATION', 21, "Directives must appear before any declarations");
-  static final ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT = new ParserErrorCode.con3('DUPLICATE_LABEL_IN_SWITCH_STATEMENT', 22, "The label %s was already used in this switch statement");
-  static final ParserErrorCode DUPLICATED_MODIFIER = new ParserErrorCode.con3('DUPLICATED_MODIFIER', 23, "The modifier '%s' was already specified.");
-  static final ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND = new ParserErrorCode.con3('EQUALITY_CANNOT_BE_EQUALITY_OPERAND', 24, "Equality expression cannot be operand of another equality expression.");
-  static final ParserErrorCode EXPECTED_CASE_OR_DEFAULT = new ParserErrorCode.con3('EXPECTED_CASE_OR_DEFAULT', 25, "Expected 'case' or 'default'");
-  static final ParserErrorCode EXPECTED_CLASS_MEMBER = new ParserErrorCode.con3('EXPECTED_CLASS_MEMBER', 26, "Expected a class member");
-  static final ParserErrorCode EXPECTED_EXECUTABLE = new ParserErrorCode.con3('EXPECTED_EXECUTABLE', 27, "Expected a method, getter, setter or operator declaration");
-  static final ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = new ParserErrorCode.con3('EXPECTED_LIST_OR_MAP_LITERAL', 28, "Expected a list or map literal");
-  static final ParserErrorCode EXPECTED_STRING_LITERAL = new ParserErrorCode.con3('EXPECTED_STRING_LITERAL', 29, "Expected a string literal");
-  static final ParserErrorCode EXPECTED_TOKEN = new ParserErrorCode.con3('EXPECTED_TOKEN', 30, "Expected to find '%s'");
-  static final ParserErrorCode EXPECTED_ONE_LIST_TYPE_ARGUMENTS = new ParserErrorCode.con3('EXPECTED_ONE_LIST_TYPE_ARGUMENTS', 31, "List literal requires exactly one type arguments or none, but %d found");
-  static final ParserErrorCode EXPECTED_TWO_MAP_TYPE_ARGUMENTS = new ParserErrorCode.con3('EXPECTED_TWO_MAP_TYPE_ARGUMENTS', 32, "Map literal requires exactly two type arguments or none, but %d found");
-  static final ParserErrorCode EXPECTED_TYPE_NAME = new ParserErrorCode.con3('EXPECTED_TYPE_NAME', 33, "Expected a type name");
-  static final ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new ParserErrorCode.con3('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 34, "Export directives must preceed part directives");
-  static final ParserErrorCode EXTERNAL_AFTER_CONST = new ParserErrorCode.con3('EXTERNAL_AFTER_CONST', 35, "The modifier 'external' should be before the modifier 'const'");
-  static final ParserErrorCode EXTERNAL_AFTER_FACTORY = new ParserErrorCode.con3('EXTERNAL_AFTER_FACTORY', 36, "The modifier 'external' should be before the modifier 'factory'");
-  static final ParserErrorCode EXTERNAL_AFTER_STATIC = new ParserErrorCode.con3('EXTERNAL_AFTER_STATIC', 37, "The modifier 'external' should be before the modifier 'static'");
-  static final ParserErrorCode EXTERNAL_CLASS = new ParserErrorCode.con3('EXTERNAL_CLASS', 38, "Classes cannot be declared to be 'external'");
-  static final ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_CONSTRUCTOR_WITH_BODY', 39, "External constructors cannot have a body");
-  static final ParserErrorCode EXTERNAL_FIELD = new ParserErrorCode.con3('EXTERNAL_FIELD', 40, "Fields cannot be declared to be 'external'");
-  static final ParserErrorCode EXTERNAL_GETTER_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_GETTER_WITH_BODY', 41, "External getters cannot have a body");
-  static final ParserErrorCode EXTERNAL_METHOD_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_METHOD_WITH_BODY', 42, "External methods cannot have a body");
-  static final ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_OPERATOR_WITH_BODY', 43, "External operators cannot have a body");
-  static final ParserErrorCode EXTERNAL_SETTER_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_SETTER_WITH_BODY', 44, "External setters cannot have a body");
-  static final ParserErrorCode EXTERNAL_TYPEDEF = new ParserErrorCode.con3('EXTERNAL_TYPEDEF', 45, "Type aliases cannot be declared to be 'external'");
-  static final ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = new ParserErrorCode.con3('FACTORY_TOP_LEVEL_DECLARATION', 46, "Top-level declarations cannot be declared to be 'factory'");
-  static final ParserErrorCode FACTORY_WITHOUT_BODY = new ParserErrorCode.con3('FACTORY_WITHOUT_BODY', 47, "A non-redirecting 'factory' constructor must have a body");
-  static final ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new ParserErrorCode.con3('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 48, "Field initializers can only be used in a constructor");
-  static final ParserErrorCode FINAL_AND_VAR = new ParserErrorCode.con3('FINAL_AND_VAR', 49, "Members cannot be declared to be both 'final' and 'var'");
-  static final ParserErrorCode FINAL_CLASS = new ParserErrorCode.con3('FINAL_CLASS', 50, "Classes cannot be declared to be 'final'");
-  static final ParserErrorCode FINAL_CONSTRUCTOR = new ParserErrorCode.con3('FINAL_CONSTRUCTOR', 51, "A constructor cannot be declared to be 'final'");
-  static final ParserErrorCode FINAL_METHOD = new ParserErrorCode.con3('FINAL_METHOD', 52, "Getters, setters and methods cannot be declared to be 'final'");
-  static final ParserErrorCode FINAL_TYPEDEF = new ParserErrorCode.con3('FINAL_TYPEDEF', 53, "Type aliases cannot be declared to be 'final'");
-  static final ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = new ParserErrorCode.con3('FUNCTION_TYPED_PARAMETER_VAR', 54, "Function typed parameters cannot specify 'const', 'final' or 'var' instead of return type");
-  static final ParserErrorCode GETTER_IN_FUNCTION = new ParserErrorCode.con3('GETTER_IN_FUNCTION', 55, "Getters cannot be defined within methods or functions");
-  static final ParserErrorCode GETTER_WITH_PARAMETERS = new ParserErrorCode.con3('GETTER_WITH_PARAMETERS', 56, "Getter should be declared without a parameter list");
-  static final ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = new ParserErrorCode.con3('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE', 57, "Illegal assignment to non-assignable expression");
-  static final ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS = new ParserErrorCode.con3('IMPLEMENTS_BEFORE_EXTENDS', 58, "The extends clause must be before the implements clause");
-  static final ParserErrorCode IMPLEMENTS_BEFORE_WITH = new ParserErrorCode.con3('IMPLEMENTS_BEFORE_WITH', 59, "The with clause must be before the implements clause");
-  static final ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new ParserErrorCode.con3('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 60, "Import directives must preceed part directives");
-  static final ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH = new ParserErrorCode.con3('INITIALIZED_VARIABLE_IN_FOR_EACH', 61, "The loop variable in a for-each loop cannot be initialized");
-  static final ParserErrorCode INVALID_CODE_POINT = new ParserErrorCode.con3('INVALID_CODE_POINT', 62, "The escape sequence '%s' is not a valid code point");
-  static final ParserErrorCode INVALID_COMMENT_REFERENCE = new ParserErrorCode.con3('INVALID_COMMENT_REFERENCE', 63, "Comment references should contain a possibly prefixed identifier and can start with 'new', but should not contain anything else");
-  static final ParserErrorCode INVALID_HEX_ESCAPE = new ParserErrorCode.con3('INVALID_HEX_ESCAPE', 64, "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
-  static final ParserErrorCode INVALID_OPERATOR = new ParserErrorCode.con3('INVALID_OPERATOR', 65, "The string '%s' is not a valid operator");
-  static final ParserErrorCode INVALID_OPERATOR_FOR_SUPER = new ParserErrorCode.con3('INVALID_OPERATOR_FOR_SUPER', 66, "The operator '%s' cannot be used with 'super'");
-  static final ParserErrorCode INVALID_UNICODE_ESCAPE = new ParserErrorCode.con3('INVALID_UNICODE_ESCAPE', 67, "An escape sequence starting with '\\u' must be followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
-  static final ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST = new ParserErrorCode.con3('LIBRARY_DIRECTIVE_NOT_FIRST', 68, "The library directive must appear before all other directives");
-  static final ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER = new ParserErrorCode.con3('LOCAL_FUNCTION_DECLARATION_MODIFIER', 69, "Local function declarations cannot specify any modifier");
-  static final ParserErrorCode MISSING_ASSIGNABLE_SELECTOR = new ParserErrorCode.con3('MISSING_ASSIGNABLE_SELECTOR', 70, "Missing selector such as \".<identifier>\" or \"[0]\"");
-  static final ParserErrorCode MISSING_CATCH_OR_FINALLY = new ParserErrorCode.con3('MISSING_CATCH_OR_FINALLY', 71, "A try statement must have either a catch or finally clause");
-  static final ParserErrorCode MISSING_CLASS_BODY = new ParserErrorCode.con3('MISSING_CLASS_BODY', 72, "A class definition must have a body, even if it is empty");
-  static final ParserErrorCode MISSING_CLOSING_PARENTHESIS = new ParserErrorCode.con3('MISSING_CLOSING_PARENTHESIS', 73, "The closing parenthesis is missing");
-  static final ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE = new ParserErrorCode.con3('MISSING_CONST_FINAL_VAR_OR_TYPE', 74, "Variables must be declared using the keywords 'const', 'final', 'var' or a type name");
-  static final ParserErrorCode MISSING_EXPRESSION_IN_THROW = new ParserErrorCode.con3('MISSING_EXPRESSION_IN_THROW', 75, "Throw expressions must compute the object to be thrown");
-  static final ParserErrorCode MISSING_FUNCTION_BODY = new ParserErrorCode.con3('MISSING_FUNCTION_BODY', 76, "A function body must be provided");
-  static final ParserErrorCode MISSING_FUNCTION_PARAMETERS = new ParserErrorCode.con3('MISSING_FUNCTION_PARAMETERS', 77, "Functions must have an explicit list of parameters");
-  static final ParserErrorCode MISSING_IDENTIFIER = new ParserErrorCode.con3('MISSING_IDENTIFIER', 78, "Expected an identifier");
-  static final ParserErrorCode MISSING_KEYWORD_OPERATOR = new ParserErrorCode.con3('MISSING_KEYWORD_OPERATOR', 79, "Operator declarations must be preceeded by the keyword 'operator'");
-  static final ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE = new ParserErrorCode.con3('MISSING_NAME_IN_LIBRARY_DIRECTIVE', 80, "Library directives must include a library name");
-  static final ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE = new ParserErrorCode.con3('MISSING_NAME_IN_PART_OF_DIRECTIVE', 81, "Library directives must include a library name");
-  static final ParserErrorCode MISSING_STATEMENT = new ParserErrorCode.con3('MISSING_STATEMENT', 82, "Expected a statement");
-  static final ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('MISSING_TERMINATOR_FOR_PARAMETER_GROUP', 83, "There is no '%s' to close the parameter group");
-  static final ParserErrorCode MISSING_TYPEDEF_PARAMETERS = new ParserErrorCode.con3('MISSING_TYPEDEF_PARAMETERS', 84, "Type aliases for functions must have an explicit list of parameters");
-  static final ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = new ParserErrorCode.con3('MISSING_VARIABLE_IN_FOR_EACH', 85, "A loop variable must be declared in a for-each loop before the 'in', but none were found");
-  static final ParserErrorCode MIXED_PARAMETER_GROUPS = new ParserErrorCode.con3('MIXED_PARAMETER_GROUPS', 86, "Cannot have both positional and named parameters in a single parameter list");
-  static final ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = new ParserErrorCode.con3('MULTIPLE_EXTENDS_CLAUSES', 87, "Each class definition can have at most one extends clause");
-  static final ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES = new ParserErrorCode.con3('MULTIPLE_IMPLEMENTS_CLAUSES', 88, "Each class definition can have at most one implements clause");
-  static final ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES = new ParserErrorCode.con3('MULTIPLE_LIBRARY_DIRECTIVES', 89, "Only one library directive may be declared in a file");
-  static final ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS = new ParserErrorCode.con3('MULTIPLE_NAMED_PARAMETER_GROUPS', 90, "Cannot have multiple groups of named parameters in a single parameter list");
-  static final ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES = new ParserErrorCode.con3('MULTIPLE_PART_OF_DIRECTIVES', 91, "Only one part-of directive may be declared in a file");
-  static final ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS = new ParserErrorCode.con3('MULTIPLE_POSITIONAL_PARAMETER_GROUPS', 92, "Cannot have multiple groups of positional parameters in a single parameter list");
-  static final ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH = new ParserErrorCode.con3('MULTIPLE_VARIABLES_IN_FOR_EACH', 93, "A single loop variable must be declared in a for-each loop before the 'in', but %s were found");
-  static final ParserErrorCode MULTIPLE_WITH_CLAUSES = new ParserErrorCode.con3('MULTIPLE_WITH_CLAUSES', 94, "Each class definition can have at most one with clause");
-  static final ParserErrorCode NAMED_FUNCTION_EXPRESSION = new ParserErrorCode.con3('NAMED_FUNCTION_EXPRESSION', 95, "Function expressions cannot be named");
-  static final ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP = new ParserErrorCode.con3('NAMED_PARAMETER_OUTSIDE_GROUP', 96, "Named parameters must be enclosed in curly braces ('{' and '}')");
-  static final ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE = new ParserErrorCode.con3('NATIVE_CLAUSE_IN_NON_SDK_CODE', 97, "Native clause can only be used in the SDK and code that is loaded through native extensions");
-  static final ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE = new ParserErrorCode.con3('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE', 98, "Native functions can only be declared in the SDK and code that is loaded through native extensions");
-  static final ParserErrorCode NON_CONSTRUCTOR_FACTORY = new ParserErrorCode.con3('NON_CONSTRUCTOR_FACTORY', 99, "Only constructors can be declared to be a 'factory'");
-  static final ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME = new ParserErrorCode.con3('NON_IDENTIFIER_LIBRARY_NAME', 100, "The name of a library must be an identifier");
-  static final ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART = new ParserErrorCode.con3('NON_PART_OF_DIRECTIVE_IN_PART', 101, "The part-of directive must be the only directive in a part");
-  static final ParserErrorCode NON_USER_DEFINABLE_OPERATOR = new ParserErrorCode.con3('NON_USER_DEFINABLE_OPERATOR', 102, "The operator '%s' is not user definable");
-  static final ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS = new ParserErrorCode.con3('NORMAL_BEFORE_OPTIONAL_PARAMETERS', 103, "Normal parameters must occur before optional parameters");
-  static final ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT = new ParserErrorCode.con3('POSITIONAL_AFTER_NAMED_ARGUMENT', 104, "Positional arguments must occur before named arguments");
-  static final ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP = new ParserErrorCode.con3('POSITIONAL_PARAMETER_OUTSIDE_GROUP', 105, "Positional parameters must be enclosed in square brackets ('[' and ']')");
-  static final ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR = new ParserErrorCode.con3('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR', 106, "Only factory constructor can specify '=' redirection.");
-  static final ParserErrorCode SETTER_IN_FUNCTION = new ParserErrorCode.con3('SETTER_IN_FUNCTION', 107, "Setters cannot be defined within methods or functions");
-  static final ParserErrorCode STATIC_AFTER_CONST = new ParserErrorCode.con3('STATIC_AFTER_CONST', 108, "The modifier 'static' should be before the modifier 'const'");
-  static final ParserErrorCode STATIC_AFTER_FINAL = new ParserErrorCode.con3('STATIC_AFTER_FINAL', 109, "The modifier 'static' should be before the modifier 'final'");
-  static final ParserErrorCode STATIC_AFTER_VAR = new ParserErrorCode.con3('STATIC_AFTER_VAR', 110, "The modifier 'static' should be before the modifier 'var'");
-  static final ParserErrorCode STATIC_CONSTRUCTOR = new ParserErrorCode.con3('STATIC_CONSTRUCTOR', 111, "Constructors cannot be static");
-  static final ParserErrorCode STATIC_GETTER_WITHOUT_BODY = new ParserErrorCode.con3('STATIC_GETTER_WITHOUT_BODY', 112, "A 'static' getter must have a body");
-  static final ParserErrorCode STATIC_OPERATOR = new ParserErrorCode.con3('STATIC_OPERATOR', 113, "Operators cannot be static");
-  static final ParserErrorCode STATIC_SETTER_WITHOUT_BODY = new ParserErrorCode.con3('STATIC_SETTER_WITHOUT_BODY', 114, "A 'static' setter must have a body");
-  static final ParserErrorCode STATIC_TOP_LEVEL_DECLARATION = new ParserErrorCode.con3('STATIC_TOP_LEVEL_DECLARATION', 115, "Top-level declarations cannot be declared to be 'static'");
-  static final ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE = new ParserErrorCode.con3('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE', 116, "The 'default' case should be the last case in a switch statement");
-  static final ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES = new ParserErrorCode.con3('SWITCH_HAS_MULTIPLE_DEFAULT_CASES', 117, "The 'default' case can only be declared once");
-  static final ParserErrorCode TOP_LEVEL_OPERATOR = new ParserErrorCode.con3('TOP_LEVEL_OPERATOR', 118, "Operators must be declared within a class");
-  static final ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP', 119, "There is no '%s' to open a parameter group");
-  static final ParserErrorCode UNEXPECTED_TOKEN = new ParserErrorCode.con3('UNEXPECTED_TOKEN', 120, "Unexpected token '%s'");
-  static final ParserErrorCode WITH_BEFORE_EXTENDS = new ParserErrorCode.con3('WITH_BEFORE_EXTENDS', 121, "The extends clause must be before the with clause");
-  static final ParserErrorCode WITH_WITHOUT_EXTENDS = new ParserErrorCode.con3('WITH_WITHOUT_EXTENDS', 122, "The with clause cannot be used without an extends clause");
-  static final ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER = new ParserErrorCode.con3('WRONG_SEPARATOR_FOR_NAMED_PARAMETER', 123, "The default value of a named parameter should be preceeded by ':'");
-  static final ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER = new ParserErrorCode.con3('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER', 124, "The default value of a positional parameter should be preceeded by '='");
-  static final ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('WRONG_TERMINATOR_FOR_PARAMETER_GROUP', 125, "Expected '%s' to close parameter group");
-  static final ParserErrorCode VAR_AND_TYPE = new ParserErrorCode.con3('VAR_AND_TYPE', 126, "Variables cannot be declared using both 'var' and a type name; remove the 'var'");
-  static final ParserErrorCode VAR_AS_TYPE_NAME = new ParserErrorCode.con3('VAR_AS_TYPE_NAME', 127, "The keyword 'var' cannot be used as a type name");
-  static final ParserErrorCode VAR_CLASS = new ParserErrorCode.con3('VAR_CLASS', 128, "Classes cannot be declared to be 'var'");
-  static final ParserErrorCode VAR_RETURN_TYPE = new ParserErrorCode.con3('VAR_RETURN_TYPE', 129, "The return type cannot be 'var'");
-  static final ParserErrorCode VAR_TYPEDEF = new ParserErrorCode.con3('VAR_TYPEDEF', 130, "Type aliases cannot be declared to be 'var'");
-  static final ParserErrorCode VOID_PARAMETER = new ParserErrorCode.con3('VOID_PARAMETER', 131, "Parameters cannot have a type of 'void'");
-  static final ParserErrorCode VOID_VARIABLE = new ParserErrorCode.con3('VOID_VARIABLE', 132, "Variables cannot have a type of 'void'");
+  static final ParserErrorCode DEPRECATED_CLASS_TYPE_ALIAS = new ParserErrorCode.con3('DEPRECATED_CLASS_TYPE_ALIAS', 21, "The 'typedef' mixin application was replaced with 'class'");
+  static final ParserErrorCode DIRECTIVE_AFTER_DECLARATION = new ParserErrorCode.con3('DIRECTIVE_AFTER_DECLARATION', 22, "Directives must appear before any declarations");
+  static final ParserErrorCode DUPLICATE_LABEL_IN_SWITCH_STATEMENT = new ParserErrorCode.con3('DUPLICATE_LABEL_IN_SWITCH_STATEMENT', 23, "The label %s was already used in this switch statement");
+  static final ParserErrorCode DUPLICATED_MODIFIER = new ParserErrorCode.con3('DUPLICATED_MODIFIER', 24, "The modifier '%s' was already specified.");
+  static final ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND = new ParserErrorCode.con3('EQUALITY_CANNOT_BE_EQUALITY_OPERAND', 25, "Equality expression cannot be operand of another equality expression.");
+  static final ParserErrorCode EXPECTED_CASE_OR_DEFAULT = new ParserErrorCode.con3('EXPECTED_CASE_OR_DEFAULT', 26, "Expected 'case' or 'default'");
+  static final ParserErrorCode EXPECTED_CLASS_MEMBER = new ParserErrorCode.con3('EXPECTED_CLASS_MEMBER', 27, "Expected a class member");
+  static final ParserErrorCode EXPECTED_EXECUTABLE = new ParserErrorCode.con3('EXPECTED_EXECUTABLE', 28, "Expected a method, getter, setter or operator declaration");
+  static final ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = new ParserErrorCode.con3('EXPECTED_LIST_OR_MAP_LITERAL', 29, "Expected a list or map literal");
+  static final ParserErrorCode EXPECTED_STRING_LITERAL = new ParserErrorCode.con3('EXPECTED_STRING_LITERAL', 30, "Expected a string literal");
+  static final ParserErrorCode EXPECTED_TOKEN = new ParserErrorCode.con3('EXPECTED_TOKEN', 31, "Expected to find '%s'");
+  static final ParserErrorCode EXPECTED_TYPE_NAME = new ParserErrorCode.con3('EXPECTED_TYPE_NAME', 32, "Expected a type name");
+  static final ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new ParserErrorCode.con3('EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 33, "Export directives must preceed part directives");
+  static final ParserErrorCode EXTERNAL_AFTER_CONST = new ParserErrorCode.con3('EXTERNAL_AFTER_CONST', 34, "The modifier 'external' should be before the modifier 'const'");
+  static final ParserErrorCode EXTERNAL_AFTER_FACTORY = new ParserErrorCode.con3('EXTERNAL_AFTER_FACTORY', 35, "The modifier 'external' should be before the modifier 'factory'");
+  static final ParserErrorCode EXTERNAL_AFTER_STATIC = new ParserErrorCode.con3('EXTERNAL_AFTER_STATIC', 36, "The modifier 'external' should be before the modifier 'static'");
+  static final ParserErrorCode EXTERNAL_CLASS = new ParserErrorCode.con3('EXTERNAL_CLASS', 37, "Classes cannot be declared to be 'external'");
+  static final ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_CONSTRUCTOR_WITH_BODY', 38, "External constructors cannot have a body");
+  static final ParserErrorCode EXTERNAL_FIELD = new ParserErrorCode.con3('EXTERNAL_FIELD', 39, "Fields cannot be declared to be 'external'");
+  static final ParserErrorCode EXTERNAL_GETTER_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_GETTER_WITH_BODY', 40, "External getters cannot have a body");
+  static final ParserErrorCode EXTERNAL_METHOD_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_METHOD_WITH_BODY', 41, "External methods cannot have a body");
+  static final ParserErrorCode EXTERNAL_OPERATOR_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_OPERATOR_WITH_BODY', 42, "External operators cannot have a body");
+  static final ParserErrorCode EXTERNAL_SETTER_WITH_BODY = new ParserErrorCode.con3('EXTERNAL_SETTER_WITH_BODY', 43, "External setters cannot have a body");
+  static final ParserErrorCode EXTERNAL_TYPEDEF = new ParserErrorCode.con3('EXTERNAL_TYPEDEF', 44, "Type aliases cannot be declared to be 'external'");
+  static final ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = new ParserErrorCode.con3('FACTORY_TOP_LEVEL_DECLARATION', 45, "Top-level declarations cannot be declared to be 'factory'");
+  static final ParserErrorCode FACTORY_WITHOUT_BODY = new ParserErrorCode.con3('FACTORY_WITHOUT_BODY', 46, "A non-redirecting 'factory' constructor must have a body");
+  static final ParserErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new ParserErrorCode.con3('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 47, "Field initializers can only be used in a constructor");
+  static final ParserErrorCode FINAL_AND_VAR = new ParserErrorCode.con3('FINAL_AND_VAR', 48, "Members cannot be declared to be both 'final' and 'var'");
+  static final ParserErrorCode FINAL_CLASS = new ParserErrorCode.con3('FINAL_CLASS', 49, "Classes cannot be declared to be 'final'");
+  static final ParserErrorCode FINAL_CONSTRUCTOR = new ParserErrorCode.con3('FINAL_CONSTRUCTOR', 50, "A constructor cannot be declared to be 'final'");
+  static final ParserErrorCode FINAL_METHOD = new ParserErrorCode.con3('FINAL_METHOD', 51, "Getters, setters and methods cannot be declared to be 'final'");
+  static final ParserErrorCode FINAL_TYPEDEF = new ParserErrorCode.con3('FINAL_TYPEDEF', 52, "Type aliases cannot be declared to be 'final'");
+  static final ParserErrorCode FUNCTION_TYPED_PARAMETER_VAR = new ParserErrorCode.con3('FUNCTION_TYPED_PARAMETER_VAR', 53, "Function typed parameters cannot specify 'const', 'final' or 'var' instead of return type");
+  static final ParserErrorCode GETTER_IN_FUNCTION = new ParserErrorCode.con3('GETTER_IN_FUNCTION', 54, "Getters cannot be defined within methods or functions");
+  static final ParserErrorCode GETTER_WITH_PARAMETERS = new ParserErrorCode.con3('GETTER_WITH_PARAMETERS', 55, "Getter should be declared without a parameter list");
+  static final ParserErrorCode ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE = new ParserErrorCode.con3('ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE', 56, "Illegal assignment to non-assignable expression");
+  static final ParserErrorCode IMPLEMENTS_BEFORE_EXTENDS = new ParserErrorCode.con3('IMPLEMENTS_BEFORE_EXTENDS', 57, "The extends clause must be before the implements clause");
+  static final ParserErrorCode IMPLEMENTS_BEFORE_WITH = new ParserErrorCode.con3('IMPLEMENTS_BEFORE_WITH', 58, "The with clause must be before the implements clause");
+  static final ParserErrorCode IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = new ParserErrorCode.con3('IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE', 59, "Import directives must preceed part directives");
+  static final ParserErrorCode INITIALIZED_VARIABLE_IN_FOR_EACH = new ParserErrorCode.con3('INITIALIZED_VARIABLE_IN_FOR_EACH', 60, "The loop variable in a for-each loop cannot be initialized");
+  static final ParserErrorCode INVALID_CODE_POINT = new ParserErrorCode.con3('INVALID_CODE_POINT', 61, "The escape sequence '%s' is not a valid code point");
+  static final ParserErrorCode INVALID_COMMENT_REFERENCE = new ParserErrorCode.con3('INVALID_COMMENT_REFERENCE', 62, "Comment references should contain a possibly prefixed identifier and can start with 'new', but should not contain anything else");
+  static final ParserErrorCode INVALID_HEX_ESCAPE = new ParserErrorCode.con3('INVALID_HEX_ESCAPE', 63, "An escape sequence starting with '\\x' must be followed by 2 hexidecimal digits");
+  static final ParserErrorCode INVALID_OPERATOR = new ParserErrorCode.con3('INVALID_OPERATOR', 64, "The string '%s' is not a valid operator");
+  static final ParserErrorCode INVALID_OPERATOR_FOR_SUPER = new ParserErrorCode.con3('INVALID_OPERATOR_FOR_SUPER', 65, "The operator '%s' cannot be used with 'super'");
+  static final ParserErrorCode INVALID_UNICODE_ESCAPE = new ParserErrorCode.con3('INVALID_UNICODE_ESCAPE', 66, "An escape sequence starting with '\\u' must be followed by 4 hexidecimal digits or from 1 to 6 digits between '{' and '}'");
+  static final ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST = new ParserErrorCode.con3('LIBRARY_DIRECTIVE_NOT_FIRST', 67, "The library directive must appear before all other directives");
+  static final ParserErrorCode LOCAL_FUNCTION_DECLARATION_MODIFIER = new ParserErrorCode.con3('LOCAL_FUNCTION_DECLARATION_MODIFIER', 68, "Local function declarations cannot specify any modifier");
+  static final ParserErrorCode MISSING_ASSIGNABLE_SELECTOR = new ParserErrorCode.con3('MISSING_ASSIGNABLE_SELECTOR', 69, "Missing selector such as \".<identifier>\" or \"[0]\"");
+  static final ParserErrorCode MISSING_CATCH_OR_FINALLY = new ParserErrorCode.con3('MISSING_CATCH_OR_FINALLY', 70, "A try statement must have either a catch or finally clause");
+  static final ParserErrorCode MISSING_CLASS_BODY = new ParserErrorCode.con3('MISSING_CLASS_BODY', 71, "A class definition must have a body, even if it is empty");
+  static final ParserErrorCode MISSING_CLOSING_PARENTHESIS = new ParserErrorCode.con3('MISSING_CLOSING_PARENTHESIS', 72, "The closing parenthesis is missing");
+  static final ParserErrorCode MISSING_CONST_FINAL_VAR_OR_TYPE = new ParserErrorCode.con3('MISSING_CONST_FINAL_VAR_OR_TYPE', 73, "Variables must be declared using the keywords 'const', 'final', 'var' or a type name");
+  static final ParserErrorCode MISSING_EXPRESSION_IN_THROW = new ParserErrorCode.con3('MISSING_EXPRESSION_IN_THROW', 74, "Throw expressions must compute the object to be thrown");
+  static final ParserErrorCode MISSING_FUNCTION_BODY = new ParserErrorCode.con3('MISSING_FUNCTION_BODY', 75, "A function body must be provided");
+  static final ParserErrorCode MISSING_FUNCTION_PARAMETERS = new ParserErrorCode.con3('MISSING_FUNCTION_PARAMETERS', 76, "Functions must have an explicit list of parameters");
+  static final ParserErrorCode MISSING_IDENTIFIER = new ParserErrorCode.con3('MISSING_IDENTIFIER', 77, "Expected an identifier");
+  static final ParserErrorCode MISSING_KEYWORD_OPERATOR = new ParserErrorCode.con3('MISSING_KEYWORD_OPERATOR', 78, "Operator declarations must be preceeded by the keyword 'operator'");
+  static final ParserErrorCode MISSING_NAME_IN_LIBRARY_DIRECTIVE = new ParserErrorCode.con3('MISSING_NAME_IN_LIBRARY_DIRECTIVE', 79, "Library directives must include a library name");
+  static final ParserErrorCode MISSING_NAME_IN_PART_OF_DIRECTIVE = new ParserErrorCode.con3('MISSING_NAME_IN_PART_OF_DIRECTIVE', 80, "Library directives must include a library name");
+  static final ParserErrorCode MISSING_STATEMENT = new ParserErrorCode.con3('MISSING_STATEMENT', 81, "Expected a statement");
+  static final ParserErrorCode MISSING_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('MISSING_TERMINATOR_FOR_PARAMETER_GROUP', 82, "There is no '%s' to close the parameter group");
+  static final ParserErrorCode MISSING_TYPEDEF_PARAMETERS = new ParserErrorCode.con3('MISSING_TYPEDEF_PARAMETERS', 83, "Type aliases for functions must have an explicit list of parameters");
+  static final ParserErrorCode MISSING_VARIABLE_IN_FOR_EACH = new ParserErrorCode.con3('MISSING_VARIABLE_IN_FOR_EACH', 84, "A loop variable must be declared in a for-each loop before the 'in', but none were found");
+  static final ParserErrorCode MIXED_PARAMETER_GROUPS = new ParserErrorCode.con3('MIXED_PARAMETER_GROUPS', 85, "Cannot have both positional and named parameters in a single parameter list");
+  static final ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = new ParserErrorCode.con3('MULTIPLE_EXTENDS_CLAUSES', 86, "Each class definition can have at most one extends clause");
+  static final ParserErrorCode MULTIPLE_IMPLEMENTS_CLAUSES = new ParserErrorCode.con3('MULTIPLE_IMPLEMENTS_CLAUSES', 87, "Each class definition can have at most one implements clause");
+  static final ParserErrorCode MULTIPLE_LIBRARY_DIRECTIVES = new ParserErrorCode.con3('MULTIPLE_LIBRARY_DIRECTIVES', 88, "Only one library directive may be declared in a file");
+  static final ParserErrorCode MULTIPLE_NAMED_PARAMETER_GROUPS = new ParserErrorCode.con3('MULTIPLE_NAMED_PARAMETER_GROUPS', 89, "Cannot have multiple groups of named parameters in a single parameter list");
+  static final ParserErrorCode MULTIPLE_PART_OF_DIRECTIVES = new ParserErrorCode.con3('MULTIPLE_PART_OF_DIRECTIVES', 90, "Only one part-of directive may be declared in a file");
+  static final ParserErrorCode MULTIPLE_POSITIONAL_PARAMETER_GROUPS = new ParserErrorCode.con3('MULTIPLE_POSITIONAL_PARAMETER_GROUPS', 91, "Cannot have multiple groups of positional parameters in a single parameter list");
+  static final ParserErrorCode MULTIPLE_VARIABLES_IN_FOR_EACH = new ParserErrorCode.con3('MULTIPLE_VARIABLES_IN_FOR_EACH', 92, "A single loop variable must be declared in a for-each loop before the 'in', but %s were found");
+  static final ParserErrorCode MULTIPLE_WITH_CLAUSES = new ParserErrorCode.con3('MULTIPLE_WITH_CLAUSES', 93, "Each class definition can have at most one with clause");
+  static final ParserErrorCode NAMED_FUNCTION_EXPRESSION = new ParserErrorCode.con3('NAMED_FUNCTION_EXPRESSION', 94, "Function expressions cannot be named");
+  static final ParserErrorCode NAMED_PARAMETER_OUTSIDE_GROUP = new ParserErrorCode.con3('NAMED_PARAMETER_OUTSIDE_GROUP', 95, "Named parameters must be enclosed in curly braces ('{' and '}')");
+  static final ParserErrorCode NATIVE_CLAUSE_IN_NON_SDK_CODE = new ParserErrorCode.con3('NATIVE_CLAUSE_IN_NON_SDK_CODE', 96, "Native clause can only be used in the SDK and code that is loaded through native extensions");
+  static final ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE = new ParserErrorCode.con3('NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE', 97, "Native functions can only be declared in the SDK and code that is loaded through native extensions");
+  static final ParserErrorCode NON_CONSTRUCTOR_FACTORY = new ParserErrorCode.con3('NON_CONSTRUCTOR_FACTORY', 98, "Only constructors can be declared to be a 'factory'");
+  static final ParserErrorCode NON_IDENTIFIER_LIBRARY_NAME = new ParserErrorCode.con3('NON_IDENTIFIER_LIBRARY_NAME', 99, "The name of a library must be an identifier");
+  static final ParserErrorCode NON_PART_OF_DIRECTIVE_IN_PART = new ParserErrorCode.con3('NON_PART_OF_DIRECTIVE_IN_PART', 100, "The part-of directive must be the only directive in a part");
+  static final ParserErrorCode NON_USER_DEFINABLE_OPERATOR = new ParserErrorCode.con3('NON_USER_DEFINABLE_OPERATOR', 101, "The operator '%s' is not user definable");
+  static final ParserErrorCode NORMAL_BEFORE_OPTIONAL_PARAMETERS = new ParserErrorCode.con3('NORMAL_BEFORE_OPTIONAL_PARAMETERS', 102, "Normal parameters must occur before optional parameters");
+  static final ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT = new ParserErrorCode.con3('POSITIONAL_AFTER_NAMED_ARGUMENT', 103, "Positional arguments must occur before named arguments");
+  static final ParserErrorCode POSITIONAL_PARAMETER_OUTSIDE_GROUP = new ParserErrorCode.con3('POSITIONAL_PARAMETER_OUTSIDE_GROUP', 104, "Positional parameters must be enclosed in square brackets ('[' and ']')");
+  static final ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR = new ParserErrorCode.con3('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR', 105, "Only factory constructor can specify '=' redirection.");
+  static final ParserErrorCode SETTER_IN_FUNCTION = new ParserErrorCode.con3('SETTER_IN_FUNCTION', 106, "Setters cannot be defined within methods or functions");
+  static final ParserErrorCode STATIC_AFTER_CONST = new ParserErrorCode.con3('STATIC_AFTER_CONST', 107, "The modifier 'static' should be before the modifier 'const'");
+  static final ParserErrorCode STATIC_AFTER_FINAL = new ParserErrorCode.con3('STATIC_AFTER_FINAL', 108, "The modifier 'static' should be before the modifier 'final'");
+  static final ParserErrorCode STATIC_AFTER_VAR = new ParserErrorCode.con3('STATIC_AFTER_VAR', 109, "The modifier 'static' should be before the modifier 'var'");
+  static final ParserErrorCode STATIC_CONSTRUCTOR = new ParserErrorCode.con3('STATIC_CONSTRUCTOR', 110, "Constructors cannot be static");
+  static final ParserErrorCode STATIC_GETTER_WITHOUT_BODY = new ParserErrorCode.con3('STATIC_GETTER_WITHOUT_BODY', 111, "A 'static' getter must have a body");
+  static final ParserErrorCode STATIC_OPERATOR = new ParserErrorCode.con3('STATIC_OPERATOR', 112, "Operators cannot be static");
+  static final ParserErrorCode STATIC_SETTER_WITHOUT_BODY = new ParserErrorCode.con3('STATIC_SETTER_WITHOUT_BODY', 113, "A 'static' setter must have a body");
+  static final ParserErrorCode STATIC_TOP_LEVEL_DECLARATION = new ParserErrorCode.con3('STATIC_TOP_LEVEL_DECLARATION', 114, "Top-level declarations cannot be declared to be 'static'");
+  static final ParserErrorCode SWITCH_HAS_CASE_AFTER_DEFAULT_CASE = new ParserErrorCode.con3('SWITCH_HAS_CASE_AFTER_DEFAULT_CASE', 115, "The 'default' case should be the last case in a switch statement");
+  static final ParserErrorCode SWITCH_HAS_MULTIPLE_DEFAULT_CASES = new ParserErrorCode.con3('SWITCH_HAS_MULTIPLE_DEFAULT_CASES', 116, "The 'default' case can only be declared once");
+  static final ParserErrorCode TOP_LEVEL_OPERATOR = new ParserErrorCode.con3('TOP_LEVEL_OPERATOR', 117, "Operators must be declared within a class");
+  static final ParserErrorCode UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP', 118, "There is no '%s' to open a parameter group");
+  static final ParserErrorCode UNEXPECTED_TOKEN = new ParserErrorCode.con3('UNEXPECTED_TOKEN', 119, "Unexpected token '%s'");
+  static final ParserErrorCode WITH_BEFORE_EXTENDS = new ParserErrorCode.con3('WITH_BEFORE_EXTENDS', 120, "The extends clause must be before the with clause");
+  static final ParserErrorCode WITH_WITHOUT_EXTENDS = new ParserErrorCode.con3('WITH_WITHOUT_EXTENDS', 121, "The with clause cannot be used without an extends clause");
+  static final ParserErrorCode WRONG_SEPARATOR_FOR_NAMED_PARAMETER = new ParserErrorCode.con3('WRONG_SEPARATOR_FOR_NAMED_PARAMETER', 122, "The default value of a named parameter should be preceeded by ':'");
+  static final ParserErrorCode WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER = new ParserErrorCode.con3('WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER', 123, "The default value of a positional parameter should be preceeded by '='");
+  static final ParserErrorCode WRONG_TERMINATOR_FOR_PARAMETER_GROUP = new ParserErrorCode.con3('WRONG_TERMINATOR_FOR_PARAMETER_GROUP', 124, "Expected '%s' to close parameter group");
+  static final ParserErrorCode VAR_AND_TYPE = new ParserErrorCode.con3('VAR_AND_TYPE', 125, "Variables cannot be declared using both 'var' and a type name; remove the 'var'");
+  static final ParserErrorCode VAR_AS_TYPE_NAME = new ParserErrorCode.con3('VAR_AS_TYPE_NAME', 126, "The keyword 'var' cannot be used as a type name");
+  static final ParserErrorCode VAR_CLASS = new ParserErrorCode.con3('VAR_CLASS', 127, "Classes cannot be declared to be 'var'");
+  static final ParserErrorCode VAR_RETURN_TYPE = new ParserErrorCode.con3('VAR_RETURN_TYPE', 128, "The return type cannot be 'var'");
+  static final ParserErrorCode VAR_TYPEDEF = new ParserErrorCode.con3('VAR_TYPEDEF', 129, "Type aliases cannot be declared to be 'var'");
+  static final ParserErrorCode VOID_PARAMETER = new ParserErrorCode.con3('VOID_PARAMETER', 130, "Parameters cannot have a type of 'void'");
+  static final ParserErrorCode VOID_VARIABLE = new ParserErrorCode.con3('VOID_VARIABLE', 131, "Variables cannot have a type of 'void'");
   static final List<ParserErrorCode> values = [
       ABSTRACT_CLASS_MEMBER,
       ABSTRACT_STATIC_METHOD,
@@ -5825,6 +5826,7 @@
       CONTINUE_OUTSIDE_OF_LOOP,
       CONTINUE_WITHOUT_LABEL_IN_CASE,
       DEPRECATED_ARGUMENT_DEFINITION_TEST,
+      DEPRECATED_CLASS_TYPE_ALIAS,
       DIRECTIVE_AFTER_DECLARATION,
       DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
       DUPLICATED_MODIFIER,
@@ -5835,8 +5837,6 @@
       EXPECTED_LIST_OR_MAP_LITERAL,
       EXPECTED_STRING_LITERAL,
       EXPECTED_TOKEN,
-      EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
-      EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
       EXPECTED_TYPE_NAME,
       EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
       EXTERNAL_AFTER_CONST,
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
index 4266226..0ff54ab 100644
--- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -617,17 +617,15 @@
       getter.static = variable.isStatic;
       _currentHolder.addAccessor(getter);
       variable.getter = getter;
-      if (!isFinal) {
-        PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(variable);
-        setter.setter = true;
-        setter.static = variable.isStatic;
-        ParameterElementImpl parameter = new ParameterElementImpl.con2("_${variable.name}", variable.nameOffset);
-        parameter.synthetic = true;
-        parameter.parameterKind = ParameterKind.REQUIRED;
-        setter.parameters = <ParameterElement> [parameter];
-        _currentHolder.addAccessor(setter);
-        variable.setter = setter;
-      }
+      PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(variable);
+      setter.setter = true;
+      setter.static = variable.isStatic;
+      ParameterElementImpl parameter = new ParameterElementImpl.con2("_${variable.name}", variable.nameOffset);
+      parameter.synthetic = true;
+      parameter.parameterKind = ParameterKind.REQUIRED;
+      setter.parameters = <ParameterElement> [parameter];
+      _currentHolder.addAccessor(setter);
+      variable.setter = setter;
     }
     return null;
   }
@@ -1184,7 +1182,6 @@
           List<int> lineStarts = scanner.lineStarts;
           Parser parser = new Parser(htmlSource, errorListener);
           CompilationUnit unit = parser.parseCompilationUnit(firstToken);
-          unit.lineInfo = new LineInfo(lineStarts);
           try {
             LibraryResolver resolver = new LibraryResolver(_context);
             LibraryElementImpl library = resolver.resolveEmbeddedLibrary(htmlSource, _modificationStamp, unit, true) as LibraryElementImpl;
@@ -2003,9 +2000,8 @@
    */
   void generateUnusedImportHints(ErrorReporter errorReporter) {
     for (ImportDirective unusedImport in _unusedImports) {
-      Element element = unusedImport.element;
-      if (element is ImportElement) {
-        ImportElement importElement = element as ImportElement;
+      ImportElement importElement = unusedImport.element;
+      if (importElement != null) {
         LibraryElement libraryElement = importElement.importedLibrary;
         if (libraryElement != null && libraryElement.isDartCore) {
           continue;
@@ -2111,7 +2107,7 @@
   Namespace computeNamespace(ImportDirective importDirective) {
     Namespace namespace = _namespaceMap[importDirective];
     if (namespace == null) {
-      ImportElement importElement = importDirective.element as ImportElement;
+      ImportElement importElement = importDirective.element;
       if (importElement != null) {
         NamespaceBuilder builder = new NamespaceBuilder();
         namespace = builder.createImportNamespace(importElement);
@@ -2962,6 +2958,11 @@
   Type2 _typeType;
 
   /**
+   * A utility class for the resolver to answer the question of "what are my subtypes?".
+   */
+  SubtypeManager _subtypeManager;
+
+  /**
    * The name of the method that can be implemented by a class to allow its instances to be invoked
    * as if they were a function.
    */
@@ -2985,6 +2986,7 @@
     _enableHints = options.hint;
     _dynamicType = resolver.typeProvider.dynamicType;
     _typeType = resolver.typeProvider.typeType;
+    _subtypeManager = new SubtypeManager();
   }
   Object visitAssignmentExpression(AssignmentExpression node) {
     sc.Token operator = node.operator;
@@ -3001,7 +3003,12 @@
         MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedType, methodName);
         node.propagatedElement = propagatedMethod;
         bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
-        bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+        bool shouldReportMissingMember_propagated = !shouldReportMissingMember_static && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+        if (shouldReportMissingMember_propagated) {
+          if (memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
+            shouldReportMissingMember_propagated = false;
+          }
+        }
         if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
           ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_METHOD : HintCode.UNDEFINED_METHOD) as ErrorCode;
           _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [
@@ -3025,7 +3032,12 @@
         MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedType, methodName);
         node.propagatedElement = propagatedMethod;
         bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
-        bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+        bool shouldReportMissingMember_propagated = !shouldReportMissingMember_static && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+        if (shouldReportMissingMember_propagated) {
+          if (memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
+            shouldReportMissingMember_propagated = false;
+          }
+        }
         if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
           ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
           _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [
@@ -3261,14 +3273,13 @@
         }
       }
     }
-    Element element = node.element;
-    if (element is ImportElement) {
-      ImportElement importElement = element as ImportElement;
+    ImportElement importElement = node.element;
+    if (importElement != null) {
       LibraryElement library = importElement.importedLibrary;
       if (library != null) {
         resolveCombinators(library, node.combinators);
       }
-      setMetadata(element, node);
+      setMetadata(importElement, node);
     }
     return null;
   }
@@ -3361,6 +3372,28 @@
     bool generatedWithTypePropagation = false;
     if (_enableHints && errorCode == null && staticElement == null) {
       errorCode = checkForInvocationError(target, false, propagatedElement);
+      if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
+        ClassElement classElementContext = null;
+        if (target == null) {
+          classElementContext = _resolver.enclosingClass;
+        } else {
+          Type2 type = target.bestType;
+          if (type != null) {
+            if (type.element is ClassElement) {
+              classElementContext = type.element as ClassElement;
+            }
+          }
+        }
+        if (classElementContext != null) {
+          _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
+          Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes(classElementContext);
+          for (ClassElement subtypeElement in subtypeElements) {
+            if (subtypeElement.getMethod(methodName.name) != null) {
+              errorCode = null;
+            }
+          }
+        }
+      }
       generatedWithTypePropagation = true;
     }
     if (errorCode == null) {
@@ -3419,7 +3452,12 @@
     MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName);
     node.propagatedElement = propagatedMethod;
     bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
-    bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+    bool shouldReportMissingMember_propagated = !shouldReportMissingMember_static && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+    if (shouldReportMissingMember_propagated) {
+      if (memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
+        shouldReportMissingMember_propagated = false;
+      }
+    }
     if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
       ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
       _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, node.operator, [
@@ -3482,7 +3520,12 @@
       MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName);
       node.propagatedElement = propagatedMethod;
       bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
-      bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+      bool shouldReportMissingMember_propagated = !shouldReportMissingMember_static && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+      if (shouldReportMissingMember_propagated) {
+        if (memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
+          shouldReportMissingMember_propagated = false;
+        }
+      }
       if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
         ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
         _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [
@@ -3694,10 +3737,7 @@
           if (useStaticContext) {
             targetType = getStaticType(target);
           } else {
-            targetType = getPropagatedType(target);
-            if (targetType == null) {
-              targetType = getStaticType(target);
-            }
+            targetType = target.bestType;
           }
           if (targetType == null) {
             return CompileTimeErrorCode.UNDEFINED_FUNCTION;
@@ -3722,7 +3762,12 @@
    */
   bool checkForUndefinedIndexOperator(IndexExpression node, Expression target, String methodName, MethodElement staticMethod, MethodElement propagatedMethod, Type2 staticType, Type2 propagatedType) {
     bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
-    bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+    bool shouldReportMissingMember_propagated = !shouldReportMissingMember_static && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+    if (shouldReportMissingMember_propagated) {
+      if (memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
+        shouldReportMissingMember_propagated = false;
+      }
+    }
     if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
       sc.Token leftBracket = node.leftBracket;
       sc.Token rightBracket = node.rightBracket;
@@ -3823,7 +3868,7 @@
           if (element == null) {
             element = importedElement;
           } else {
-            element = new MultiplyDefinedElementImpl.con1(definingLibrary.context, element, importedElement);
+            element = MultiplyDefinedElementImpl.fromElements(definingLibrary.context, element, importedElement);
           }
         }
       }
@@ -4017,7 +4062,7 @@
     javaSetAdd(visitedInterfaces, targetClass);
     if (includeTargetType) {
       PropertyAccessorElement getter = targetType.getGetter(getterName);
-      if (getter != null) {
+      if (getter != null && getter.isAccessibleIn(_resolver.definingLibrary)) {
         return getter;
       }
     }
@@ -4200,7 +4245,7 @@
     javaSetAdd(visitedInterfaces, targetClass);
     if (includeTargetType) {
       MethodElement method = targetType.getMethod(methodName);
-      if (method != null) {
+      if (method != null && method.isAccessibleIn(_resolver.definingLibrary)) {
         return method;
       }
     }
@@ -4270,7 +4315,7 @@
     javaSetAdd(visitedInterfaces, targetClass);
     if (includeTargetType) {
       PropertyAccessorElement setter = targetType.getSetter(setterName);
-      if (setter != null) {
+      if (setter != null && setter.isAccessibleIn(_resolver.definingLibrary)) {
         return setter;
       }
     }
@@ -4294,6 +4339,34 @@
   }
 
   /**
+   * Given some class element, this method uses [subtypeManager] to find the set of all
+   * subtypes; the subtypes are then searched for a member (method, getter, or setter), that matches
+   * a passed
+   *
+   * @param element the class element to search the subtypes of, if a non-ClassElement element is
+   *          passed, then `false` is returned
+   * @param memberName the member name to search for
+   * @param asMethod `true` if the methods should be searched for in the subtypes
+   * @param asAccessor `true` if the accessors (getters and setters) should be searched for in
+   *          the subtypes
+   * @return `true` if and only if the passed memberName was found in a subtype
+   */
+  bool memberFoundInSubclass(Element element, String memberName, bool asMethod, bool asAccessor) {
+    if (element is ClassElement) {
+      _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
+      Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes(element as ClassElement);
+      for (ClassElement subtypeElement in subtypeElements) {
+        if (asMethod && subtypeElement.getMethod(memberName) != null) {
+          return true;
+        } else if (asAccessor && (subtypeElement.getGetter(memberName) != null || subtypeElement.getSetter(memberName) != null)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
    * Return the binary operator that is invoked by the given compound assignment operator.
    *
    * @param operator the assignment operator being mapped
@@ -4595,7 +4668,12 @@
     ExecutableElement propagatedElement = resolveProperty(target, propagatedType, propertyName);
     propertyName.propagatedElement = propagatedElement;
     bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticElement) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedElement));
-    bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedElement) : false;
+    bool shouldReportMissingMember_propagated = !shouldReportMissingMember_static && _enableHints ? shouldReportMissingMember(propagatedType, propagatedElement) : false;
+    if (shouldReportMissingMember_propagated) {
+      if (memberFoundInSubclass(propagatedType.element, propertyName.name, false, true)) {
+        shouldReportMissingMember_propagated = false;
+      }
+    }
     if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
       Element selectedElement = select(staticElement, propagatedElement);
       bool isStaticProperty = isStatic(selectedElement);
@@ -5986,6 +6064,8 @@
         combinators.add(hide);
       } else {
         ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
+        show.offset = combinator.offset;
+        show.end = combinator.end;
         show.shownNames = getIdentifiers(((combinator as ShowCombinator)).shownNames);
         combinators.add(show);
       }
@@ -6734,6 +6814,15 @@
     node.accept(_typeAnalyzer);
     return null;
   }
+  Object visitBlockFunctionBody(BlockFunctionBody node) {
+    try {
+      overrideManager.enterScope();
+      super.visitBlockFunctionBody(node);
+    } finally {
+      overrideManager.exitScope();
+    }
+    return null;
+  }
   Object visitBreakStatement(BreakStatement node) {
     node.accept(_elementResolver);
     node.accept(_typeAnalyzer);
@@ -6851,6 +6940,15 @@
     }
     return null;
   }
+  Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    try {
+      overrideManager.enterScope();
+      super.visitExpressionFunctionBody(node);
+    } finally {
+      overrideManager.exitScope();
+    }
+    return null;
+  }
   Object visitFieldDeclaration(FieldDeclaration node) {
     try {
       overrideManager.enterScope();
@@ -6880,15 +6978,6 @@
     }
     return null;
   }
-  Object visitFunctionBody(FunctionBody node) {
-    try {
-      overrideManager.enterScope();
-      super.visitFunctionBody(node);
-    } finally {
-      overrideManager.exitScope();
-    }
-    return null;
-  }
   Object visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = enclosingFunction;
     try {
@@ -7456,7 +7545,7 @@
  *
  * @coverage dart.engine.resolver
  */
-abstract class ScopedVisitor extends GeneralizingASTVisitor<Object> {
+abstract class ScopedVisitor extends UnifyingASTVisitor<Object> {
 
   /**
    * The element for the library containing the compilation unit being visited.
@@ -9486,6 +9575,155 @@
   }
 }
 /**
+ * Instances of this class manage the knowledge of what the set of subtypes are for a given type.
+ */
+class SubtypeManager {
+
+  /**
+   * A map between [ClassElement]s and a set of [ClassElement]s that are subtypes of the
+   * key.
+   */
+  Map<ClassElement, Set<ClassElement>> _subtypeMap = new Map<ClassElement, Set<ClassElement>>();
+
+  /**
+   * The set of all [LibraryElement]s that have been visited by the manager. This is used both
+   * to prevent infinite loops in the recursive methods, and also as a marker for the scope of the
+   * libraries visited by this manager.
+   */
+  Set<LibraryElement> _visitedLibraries = new Set<LibraryElement>();
+
+  /**
+   * Given some [ClassElement], return the set of all subtypes, and subtypes of subtypes.
+   *
+   * @param classElement the class to recursively return the set of subtypes of
+   */
+  Set<ClassElement> computeAllSubtypes(ClassElement classElement) {
+    computeSubtypesInLibrary(classElement.library);
+    Set<ClassElement> allSubtypes = new Set<ClassElement>();
+    computeAllSubtypes2(classElement, new Set<ClassElement>(), allSubtypes);
+    return allSubtypes;
+  }
+
+  /**
+   * Given some [LibraryElement], visit all of the types in the library, the passed library,
+   * and any imported libraries, will be in the [visitedLibraries] set.
+   *
+   * @param libraryElement the library to visit, it it hasn't been visited already
+   */
+  void ensureLibraryVisited(LibraryElement libraryElement) {
+    computeSubtypesInLibrary(libraryElement);
+  }
+
+  /**
+   * Given some [ClassElement] and a [HashSet<ClassElement>], this method recursively
+   * adds all of the subtypes of the [ClassElement] to the passed array.
+   *
+   * @param classElement the type to compute the set of subtypes of
+   * @param visitedClasses the set of class elements that this method has already recursively seen
+   * @param allSubtypes the computed set of subtypes of the passed class element
+   */
+  void computeAllSubtypes2(ClassElement classElement, Set<ClassElement> visitedClasses, Set<ClassElement> allSubtypes) {
+    if (!javaSetAdd(visitedClasses, classElement)) {
+      return;
+    }
+    Set<ClassElement> subtypes = _subtypeMap[classElement];
+    if (subtypes == null) {
+      return;
+    }
+    for (ClassElement subtype in subtypes) {
+      computeAllSubtypes2(subtype, visitedClasses, allSubtypes);
+    }
+    allSubtypes.addAll(subtypes);
+  }
+
+  /**
+   * Given some [ClassElement], this method adds all of the pairs combinations of itself and
+   * all of its supertypes to the [subtypeMap] map.
+   *
+   * @param classElement the class element
+   */
+  void computeSubtypesInClass(ClassElement classElement) {
+    InterfaceType supertypeType = classElement.supertype;
+    if (supertypeType != null) {
+      ClassElement supertypeElement = supertypeType.element;
+      if (supertypeElement != null) {
+        putInSubtypeMap(supertypeElement, classElement);
+      }
+    }
+    List<InterfaceType> interfaceTypes = classElement.interfaces;
+    for (InterfaceType interfaceType in interfaceTypes) {
+      ClassElement interfaceElement = interfaceType.element;
+      if (interfaceElement != null) {
+        putInSubtypeMap(interfaceElement, classElement);
+      }
+    }
+    List<InterfaceType> mixinTypes = classElement.mixins;
+    for (InterfaceType mixinType in mixinTypes) {
+      ClassElement mixinElement = mixinType.element;
+      if (mixinElement != null) {
+        putInSubtypeMap(mixinElement, classElement);
+      }
+    }
+  }
+
+  /**
+   * Given some [CompilationUnitElement], this method calls
+   * [computeAllSubtypes] on all of the [ClassElement]s in the
+   * compilation unit.
+   *
+   * @param unitElement the compilation unit element
+   */
+  void computeSubtypesInCompilationUnit(CompilationUnitElement unitElement) {
+    List<ClassElement> classElements = unitElement.types;
+    for (ClassElement classElement in classElements) {
+      computeSubtypesInClass(classElement);
+    }
+  }
+
+  /**
+   * Given some [LibraryElement], this method calls
+   * [computeAllSubtypes] on all of the [ClassElement]s in the
+   * compilation unit, and itself for all imported and exported libraries. All visited libraries are
+   * added to the [visitedLibraries] set.
+   *
+   * @param libraryElement the library element
+   */
+  void computeSubtypesInLibrary(LibraryElement libraryElement) {
+    if (libraryElement == null || _visitedLibraries.contains(libraryElement)) {
+      return;
+    }
+    javaSetAdd(_visitedLibraries, libraryElement);
+    computeSubtypesInCompilationUnit(libraryElement.definingCompilationUnit);
+    List<CompilationUnitElement> parts = libraryElement.parts;
+    for (CompilationUnitElement part in parts) {
+      computeSubtypesInCompilationUnit(part);
+    }
+    List<LibraryElement> imports = libraryElement.importedLibraries;
+    for (LibraryElement importElt in imports) {
+      computeSubtypesInLibrary(importElt.library);
+    }
+    List<LibraryElement> exports = libraryElement.exportedLibraries;
+    for (LibraryElement exportElt in exports) {
+      computeSubtypesInLibrary(exportElt.library);
+    }
+  }
+
+  /**
+   * Add some key/ value pair into the [subtypeMap] map.
+   *
+   * @param supertypeElement the key for the [subtypeMap] map
+   * @param subtypeElement the value for the [subtypeMap] map
+   */
+  void putInSubtypeMap(ClassElement supertypeElement, ClassElement subtypeElement) {
+    Set<ClassElement> subtypes = _subtypeMap[supertypeElement];
+    if (subtypes == null) {
+      subtypes = new Set<ClassElement>();
+      _subtypeMap[supertypeElement] = subtypes;
+    }
+    javaSetAdd(subtypes, subtypeElement);
+  }
+}
+/**
  * Instances of the class `TypeOverrideManager` manage the ability to override the type of an
  * element within a given context.
  */
@@ -11130,25 +11368,18 @@
         if (foundElement == null) {
           foundElement = element;
         } else if (foundElement != element) {
-          foundElement = new MultiplyDefinedElementImpl.con1(_definingLibrary.context, foundElement, element);
+          foundElement = MultiplyDefinedElementImpl.fromElements(_definingLibrary.context, foundElement, element);
         }
       }
     }
     if (foundElement is MultiplyDefinedElementImpl) {
-      foundElement = removeSdkElements(foundElement as MultiplyDefinedElementImpl);
+      foundElement = removeSdkElements(identifier, name, foundElement as MultiplyDefinedElementImpl);
     }
     if (foundElement is MultiplyDefinedElementImpl) {
       String foundEltName = foundElement.displayName;
-      String libName1 = "", libName2 = "";
       List<Element> conflictingMembers = ((foundElement as MultiplyDefinedElementImpl)).conflictingElements;
-      LibraryElement enclosingLibrary = conflictingMembers[0].getAncestor(LibraryElement);
-      if (enclosingLibrary != null) {
-        libName1 = enclosingLibrary.definingCompilationUnit.displayName;
-      }
-      enclosingLibrary = conflictingMembers[1].getAncestor(LibraryElement);
-      if (enclosingLibrary != null) {
-        libName2 = enclosingLibrary.definingCompilationUnit.displayName;
-      }
+      String libName1 = getLibraryName(conflictingMembers[0], "");
+      String libName2 = getLibraryName(conflictingMembers[1], "");
       _errorListener.onError(new AnalysisError.con2(getSource2(identifier), identifier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltName, libName1, libName2]));
       return foundElement;
     }
@@ -11173,6 +11404,24 @@
   }
 
   /**
+   * Returns the name of the library that defines given element.
+   *
+   * @param element the element to get library name
+   * @param def the default name to use
+   * @return the name of the library that defines given element
+   */
+  String getLibraryName(Element element, String def) {
+    if (element == null) {
+      return def;
+    }
+    LibraryElement library = element.library;
+    if (library == null) {
+      return def;
+    }
+    return library.definingCompilationUnit.displayName;
+  }
+
+  /**
    * Return the source that contains the given identifier, or the source associated with this scope
    * if the source containing the identifier could not be determined.
    *
@@ -11197,18 +11446,29 @@
    * Given a collection of elements that a single name could all be mapped to, remove from the list
    * all of the names defined in the SDK. Return the element(s) that remain.
    *
+   * @param identifier the identifier node to lookup element for, used to report correct kind of a
+   *          problem and associate problem with
+   * @param name the name associated with the element
    * @param foundElement the element encapsulating the collection of elements
    * @return all of the elements that are not defined in the SDK
    */
-  Element removeSdkElements(MultiplyDefinedElementImpl foundElement) {
+  Element removeSdkElements(Identifier identifier, String name, MultiplyDefinedElementImpl foundElement) {
     List<Element> conflictingMembers = foundElement.conflictingElements;
     int length = conflictingMembers.length;
     int to = 0;
+    Element sdkElement = null;
     for (Element member in conflictingMembers) {
-      if (!member.library.isInSdk) {
+      if (member.library.isInSdk) {
+        sdkElement = member;
+      } else {
         conflictingMembers[to++] = member;
       }
     }
+    if (sdkElement != null && to > 0) {
+      String sdkLibName = getLibraryName(sdkElement, "");
+      String otherLibName = getLibraryName(conflictingMembers[0], "");
+      _errorListener.onError(new AnalysisError.con2(getSource2(identifier), identifier.offset, identifier.length, StaticWarningCode.CONFLICTING_DART_IMPORT, [name, sdkLibName, otherLibName]));
+    }
     if (to == length) {
       return foundElement;
     } else if (to == 1) {
@@ -11219,7 +11479,7 @@
     }
     List<Element> remaining = new List<Element>(to);
     JavaSystem.arraycopy(conflictingMembers, 0, remaining, 0, to);
-    return new MultiplyDefinedElementImpl.con2(_definingLibrary.context, remaining);
+    return new MultiplyDefinedElementImpl(_definingLibrary.context, remaining);
   }
 }
 /**
@@ -12311,6 +12571,7 @@
       checkForMemberWithClassName();
       checkForNoDefaultSuperConstructorImplicit(node);
       checkForAllMixinErrorCodes(withClause);
+      checkForConflictingTypeVariableErrorCodes(node);
       if (implementsClause != null || extendsClause != null) {
         if (!checkForImplementsDisallowedClass(implementsClause) && !checkForExtendsDisallowedClass(extendsClause)) {
           checkForNonAbstractClassInheritsAbstractMember(node);
@@ -12332,6 +12593,7 @@
       checkForDuplicateDefinitionInheritance();
       checkForConflictingGetterAndMethod();
       checkImplementsSuperClass(node);
+      checkImplementsFunctionWithoutCall(node);
       return super.visitClassDeclaration(node);
     } finally {
       _isInNativeClass = false;
@@ -12547,6 +12809,7 @@
         }
       }
     }
+    checkForExpectedOneListTypeArgument(node);
     checkForListElementTypeNotAssignable(node);
     return super.visitListLiteral(node);
   }
@@ -12560,8 +12823,10 @@
         }
       }
     }
+    checkExpectedTwoMapTypeArguments(typeArguments);
     checkForNonConstMapAsExpressionStatement(node);
     checkForMapTypeNotAssignable(node);
+    checkForConstMapKeyExpressionTypeImplementsEquals2(node);
     return super.visitMapLiteral(node);
   }
   Object visitMethodDeclaration(MethodDeclaration node) {
@@ -12705,6 +12970,7 @@
   }
   Object visitTypeParameter(TypeParameter node) {
     checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME);
+    checkForTypeParameterSupertypeOfItsBound(node);
     return super.visitTypeParameter(node);
   }
   Object visitVariableDeclaration(VariableDeclaration node) {
@@ -12736,6 +13002,25 @@
   }
 
   /**
+   * This verifies if the passed map literal has type arguments then there is exactly two.
+   *
+   * @param node the map literal to evaluate
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see StaticTypeWarningCode#EXPECTED_TWO_MAP_TYPE_ARGUMENTS
+   */
+  bool checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) {
+    if (typeArguments == null) {
+      return false;
+    }
+    int num = typeArguments.arguments.length;
+    if (num == 2) {
+      return false;
+    }
+    _errorReporter.reportError2(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, typeArguments, [num]);
+    return true;
+  }
+
+  /**
    * This verifies that the passed constructor declaration does not violate any of the error codes
    * relating to the initialization of fields in the enclosing class.
    *
@@ -12917,9 +13202,9 @@
           overriddenExecutable.enclosingElement.displayName]);
       return true;
     }
-    if (overridingPositionalPT.length < overriddenPositionalPT.length) {
+    if (overridingNormalPT.length + overridingPositionalPT.length < overriddenPositionalPT.length + overriddenNormalPT.length) {
       _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_POSITIONAL, errorNameTarget, [
-          overriddenPositionalPT.length,
+          overriddenPositionalPT.length + overriddenNormalPT.length,
           overriddenExecutable.enclosingElement.displayName]);
       return true;
     }
@@ -13181,7 +13466,7 @@
     Type2 redirectedReturnType = redirectedType.returnType;
     FunctionType constructorType = node.element.type;
     Type2 constructorReturnType = constructorType.returnType;
-    if (!redirectedReturnType.isSubtypeOf(constructorReturnType)) {
+    if (!redirectedReturnType.isAssignableTo(constructorReturnType)) {
       _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE, redirectedNode, [redirectedReturnType, constructorReturnType]);
       return true;
     }
@@ -13515,19 +13800,10 @@
    * @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
    */
   bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 type) {
-    if (type == null || type == _typeProvider.intType || type == _typeProvider.stringType) {
+    if (!implementsEqualsWhenNotAllowed(type)) {
       return false;
     }
-    Element element = type.element;
-    if (element is! ClassElement) {
-      return false;
-    }
-    ClassElement classElement = element as ClassElement;
-    MethodElement method = classElement.lookUpMethod("==", _currentLibrary);
-    if (method == null || method.enclosingElement.type.isObject) {
-      return false;
-    }
-    _errorReporter.reportError4(CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, node.keyword, [element.displayName]);
+    _errorReporter.reportError4(CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, node.keyword, [type.displayName]);
     return true;
   }
 
@@ -13762,6 +14038,30 @@
   }
 
   /**
+   * This verifies all conflicts between type variable and enclosing class. TODO(scheglov)
+   *
+   * @param node the class declaration to evaluate
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_CLASS
+   * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+   */
+  bool checkForConflictingTypeVariableErrorCodes(ClassDeclaration node) {
+    bool problemReported = false;
+    for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) {
+      String name = typeParameter.name;
+      if (_enclosingClass.name == name) {
+        _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS, typeParameter.nameOffset, name.length, [name]);
+        problemReported = true;
+      }
+      if (_enclosingClass.getMethod(name) != null || _enclosingClass.getGetter(name) != null || _enclosingClass.getSetter(name) != null) {
+        _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER, typeParameter.nameOffset, name.length, [name]);
+        problemReported = true;
+      }
+    }
+    return problemReported;
+  }
+
+  /**
    * This verifies that if the passed constructor declaration is 'const' then there are no
    * invocations of non-'const' super constructors.
    *
@@ -13858,6 +14158,43 @@
   }
 
   /**
+   * This verifies that the passed expression (used as a key in constant map) has class type that
+   * does not declare operator <i>==<i>.
+   *
+   * @param key the expression to evaluate
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
+   */
+  bool checkForConstMapKeyExpressionTypeImplementsEquals(Expression key) {
+    Type2 type = key.staticType;
+    if (!implementsEqualsWhenNotAllowed(type)) {
+      return false;
+    }
+    _errorReporter.reportError2(CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, key, [type.displayName]);
+    return true;
+  }
+
+  /**
+   * This verifies that the all keys of the passed map literal have class type that does not declare
+   * operator <i>==<i>.
+   *
+   * @param key the map literal to evaluate
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
+   */
+  bool checkForConstMapKeyExpressionTypeImplementsEquals2(MapLiteral node) {
+    if (node.constKeyword == null) {
+      return false;
+    }
+    bool hasProblems = false;
+    for (MapLiteralEntry entry in node.entries) {
+      Expression key = entry.key;
+      hasProblems = javaBooleanOr(hasProblems, checkForConstMapKeyExpressionTypeImplementsEquals(key));
+    }
+    return hasProblems;
+  }
+
+  /**
    * This verifies that the passed instance creation expression is not being invoked on an abstract
    * class.
    *
@@ -14078,6 +14415,26 @@
   }
 
   /**
+   * This verifies if the passed list literal has type arguments then there is exactly one.
+   *
+   * @param node the list literal to evaluate
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see StaticTypeWarningCode#EXPECTED_ONE_LIST_TYPE_ARGUMENTS
+   */
+  bool checkForExpectedOneListTypeArgument(ListLiteral node) {
+    TypeArgumentList typeArguments = node.typeArguments;
+    if (typeArguments == null) {
+      return false;
+    }
+    int num = typeArguments.arguments.length;
+    if (num == 1) {
+      return false;
+    }
+    _errorReporter.reportError2(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, typeArguments, [num]);
+    return true;
+  }
+
+  /**
    * This verifies the passed import has unique name among other exported libraries.
    *
    * @param node the export directive to evaluate
@@ -14407,11 +14764,10 @@
    * @see CompileTimeErrorCode#IMPORT_DUPLICATED_LIBRARY_NAME
    */
   bool checkForImportDuplicateLibraryName(ImportDirective node) {
-    Element nodeElement = node.element;
-    if (nodeElement is! ImportElement) {
+    ImportElement nodeImportElement = node.element;
+    if (nodeImportElement == null) {
       return false;
     }
-    ImportElement nodeImportElement = nodeElement as ImportElement;
     LibraryElement nodeLibrary = nodeImportElement.importedLibrary;
     if (nodeLibrary == null) {
       return false;
@@ -14444,11 +14800,10 @@
     if (_isInSystemLibrary) {
       return false;
     }
-    Element element = node.element;
-    if (element is! ImportElement) {
+    ImportElement importElement = node.element;
+    if (importElement == null) {
       return false;
     }
-    ImportElement importElement = element as ImportElement;
     DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk;
     String uri = importElement.uri;
     SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri);
@@ -15622,18 +15977,19 @@
     if (node.typeArguments == null) {
       return false;
     }
-    List<TypeParameterElement> boundingElts = null;
     Type2 type = node.type;
     if (type == null) {
       return false;
     }
     Element element = type.element;
-    if (element is ClassElement) {
-      boundingElts = ((element as ClassElement)).typeParameters;
-    } else {
+    if (element is! ClassElement) {
       return false;
     }
+    ClassElement classElement = element as ClassElement;
+    List<Type2> typeParameters = classElement.type.typeArguments;
+    List<TypeParameterElement> boundingElts = classElement.typeParameters;
     NodeList<TypeName> typeNameArgList = node.typeArguments.arguments;
+    List<Type2> typeArguments = ((type as InterfaceType)).typeArguments;
     int loopThroughIndex = Math.min(typeNameArgList.length, boundingElts.length);
     bool foundError = false;
     for (int i = 0; i < loopThroughIndex; i++) {
@@ -15641,6 +15997,7 @@
       Type2 argType = argTypeName.type;
       Type2 boundType = boundingElts[i].bound;
       if (argType != null && boundType != null) {
+        boundType = boundType.substitute2(typeArguments, typeParameters);
         if (!argType.isSubtypeOf(boundType)) {
           ErrorCode errorCode;
           if (isInConstConstructorInvocation(node)) {
@@ -15676,6 +16033,26 @@
   }
 
   /**
+   * This checks that if the passed type parameter is a supertype of its bound.
+   *
+   * @param node the type parameter to evaluate
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see StaticTypeWarningCode#TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND
+   */
+  bool checkForTypeParameterSupertypeOfItsBound(TypeParameter node) {
+    TypeParameterElement element = node.element;
+    Type2 bound = element.bound;
+    if (bound == null) {
+      return false;
+    }
+    if (!bound.isMoreSpecificThan(element.type)) {
+      return false;
+    }
+    _errorReporter.reportError2(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, node, [element.displayName]);
+    return true;
+  }
+
+  /**
    * This checks that if the passed generative constructor has neither an explicit super constructor
    * invocation nor a redirecting constructor invocation, that the superclass has a default
    * generative constructor.
@@ -15819,6 +16196,32 @@
   }
 
   /**
+   * This verifies that if the given class declaration implements the class Function that it has a
+   * concrete implementation of the call method.
+   *
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see StaticWarningCode#FUNCTION_WITHOUT_CALL
+   */
+  bool checkImplementsFunctionWithoutCall(ClassDeclaration node) {
+    if (node.abstractKeyword != null) {
+      return false;
+    }
+    ClassElement classElement = node.element;
+    if (classElement == null) {
+      return false;
+    }
+    if (!classElement.type.isSubtypeOf(_typeProvider.functionType)) {
+      return false;
+    }
+    ExecutableElement callMethod = _inheritanceManager.lookupMember(classElement, "call");
+    if (callMethod == null || callMethod is! MethodElement || ((callMethod as MethodElement)).isAbstract) {
+      _errorReporter.reportError2(StaticWarningCode.FUNCTION_WITHOUT_CALL, node.name, []);
+      return true;
+    }
+    return false;
+  }
+
+  /**
    * This verifies that the given class declaration does not have the same class in the 'extends'
    * and 'implements' clauses.
    *
@@ -15955,6 +16358,26 @@
       javaSetAdd(checked, current);
     }
   }
+
+  /**
+   * @return `true` if given [Type] implements operator <i>==</i>, and it is not
+   *         <i>int</i> or <i>String</i>.
+   */
+  bool implementsEqualsWhenNotAllowed(Type2 type) {
+    if (type == null || type == _typeProvider.intType || type == _typeProvider.stringType) {
+      return false;
+    }
+    Element element = type.element;
+    if (element is! ClassElement) {
+      return false;
+    }
+    ClassElement classElement = element as ClassElement;
+    MethodElement method = classElement.lookUpMethod("==", _currentLibrary);
+    if (method == null || method.enclosingElement.type.isObject) {
+      return false;
+    }
+    return true;
+  }
   bool isFunctionType(Type2 type) {
     if (type.isDynamic || type.isBottom) {
       return true;
diff --git a/pkg/analyzer_experimental/lib/src/generated/scanner.dart b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
index b255e75..81652aa 100644
--- a/pkg/analyzer_experimental/lib/src/generated/scanner.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
@@ -427,6 +427,11 @@
   List<BeginToken> _groupingStack = new List<BeginToken>();
 
   /**
+   * The index of the last item in the [groupingStack], or `-1` if the stack is empty.
+   */
+  int _stackEnd = -1;
+
+  /**
    * A flag indicating whether any unmatched groups were found during the parse.
    */
   bool _hasUnmatchedGroups2 = false;
@@ -535,6 +540,7 @@
     }
     _tail = _tail.setNext(token);
     _groupingStack.add(token);
+    _stackEnd++;
   }
   void appendCommentToken(TokenType type, String value) {
     if (_firstComment == null) {
@@ -554,12 +560,11 @@
       _lastComment = null;
     }
     _tail = _tail.setNext(token);
-    int last = _groupingStack.length - 1;
-    if (last >= 0) {
-      BeginToken begin = _groupingStack[last];
+    if (_stackEnd >= 0) {
+      BeginToken begin = _groupingStack[_stackEnd];
       if (identical(begin.type, beginType)) {
         begin.endToken = token;
-        _groupingStack.removeAt(last);
+        _groupingStack.removeAt(_stackEnd--);
       }
     }
   }
@@ -574,7 +579,7 @@
     }
     eofToken.setNext(eofToken);
     _tail = _tail.setNext(eofToken);
-    if (!_groupingStack.isEmpty) {
+    if (_stackEnd >= 0) {
       _hasUnmatchedGroups2 = true;
     }
   }
@@ -775,15 +780,13 @@
    * @return the token to be paired with the closing brace
    */
   BeginToken findTokenMatchingClosingBraceInInterpolationExpression() {
-    int last = _groupingStack.length - 1;
-    while (last >= 0) {
-      BeginToken begin = _groupingStack[last];
+    while (_stackEnd >= 0) {
+      BeginToken begin = _groupingStack[_stackEnd];
       if (identical(begin.type, TokenType.OPEN_CURLY_BRACKET) || identical(begin.type, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
         return begin;
       }
       _hasUnmatchedGroups2 = true;
-      _groupingStack.removeAt(last);
-      last--;
+      _groupingStack.removeAt(_stackEnd--);
     }
     return null;
   }
diff --git a/pkg/analyzer_experimental/test/generated/ast_test.dart b/pkg/analyzer_experimental/test/generated/ast_test.dart
index 0c07d4c..f90e9a3 100644
--- a/pkg/analyzer_experimental/test/generated/ast_test.dart
+++ b/pkg/analyzer_experimental/test/generated/ast_test.dart
@@ -254,7 +254,7 @@
   static CatchClause catchClause4(TypeName exceptionType, String exceptionParameter, List<Statement> statements) => catchClause5(exceptionType, exceptionParameter, null, statements);
   static CatchClause catchClause5(TypeName exceptionType, String exceptionParameter, String stackTraceParameter, List<Statement> statements) => new CatchClause.full(exceptionType == null ? null : TokenFactory.token4(TokenType.IDENTIFIER, "on"), exceptionType, exceptionParameter == null ? null : TokenFactory.token(Keyword.CATCH), exceptionParameter == null ? null : TokenFactory.token3(TokenType.OPEN_PAREN), identifier3(exceptionParameter), stackTraceParameter == null ? null : TokenFactory.token3(TokenType.COMMA), stackTraceParameter == null ? null : identifier3(stackTraceParameter), exceptionParameter == null ? null : TokenFactory.token3(TokenType.CLOSE_PAREN), block(statements));
   static ClassDeclaration classDeclaration(Keyword abstractKeyword, String name, TypeParameterList typeParameters, ExtendsClause extendsClause, WithClause withClause, ImplementsClause implementsClause, List<ClassMember> members) => new ClassDeclaration.full(null, null, abstractKeyword == null ? null : TokenFactory.token(abstractKeyword), TokenFactory.token(Keyword.CLASS), identifier3(name), typeParameters, extendsClause, withClause, implementsClause, TokenFactory.token3(TokenType.OPEN_CURLY_BRACKET), list(members), TokenFactory.token3(TokenType.CLOSE_CURLY_BRACKET));
-  static ClassTypeAlias classTypeAlias(String name, TypeParameterList typeParameters, Keyword abstractKeyword, TypeName superclass, WithClause withClause, ImplementsClause implementsClause) => new ClassTypeAlias.full(null, null, TokenFactory.token(Keyword.TYPEDEF), identifier3(name), typeParameters, TokenFactory.token3(TokenType.EQ), abstractKeyword == null ? null : TokenFactory.token(abstractKeyword), superclass, withClause, implementsClause, TokenFactory.token3(TokenType.SEMICOLON));
+  static ClassTypeAlias classTypeAlias(String name, TypeParameterList typeParameters, Keyword abstractKeyword, TypeName superclass, WithClause withClause, ImplementsClause implementsClause) => new ClassTypeAlias.full(null, null, TokenFactory.token(Keyword.CLASS), identifier3(name), typeParameters, TokenFactory.token3(TokenType.EQ), abstractKeyword == null ? null : TokenFactory.token(abstractKeyword), superclass, withClause, implementsClause, TokenFactory.token3(TokenType.SEMICOLON));
   static CompilationUnit compilationUnit() => compilationUnit8(null, null, null);
   static CompilationUnit compilationUnit2(List<CompilationUnitMember> declarations) => compilationUnit8(null, null, list(declarations));
   static CompilationUnit compilationUnit3(List<Directive> directives) => compilationUnit8(null, list(directives), null);
@@ -801,6 +801,270 @@
     return super.visitNode(node);
   }
 }
+class NodeListTest extends EngineTestCase {
+  void test_add() {
+    ASTNode parent = ASTFactory.argumentList([]);
+    ASTNode firstNode = ASTFactory.booleanLiteral(true);
+    ASTNode secondNode = ASTFactory.booleanLiteral(false);
+    NodeList<ASTNode> list = new NodeList<ASTNode>(parent);
+    list.insert(0, secondNode);
+    list.insert(0, firstNode);
+    EngineTestCase.assertSize(2, list);
+    JUnitTestCase.assertSame(firstNode, list[0]);
+    JUnitTestCase.assertSame(secondNode, list[1]);
+    JUnitTestCase.assertSame(parent, firstNode.parent);
+    JUnitTestCase.assertSame(parent, secondNode.parent);
+    ASTNode thirdNode = ASTFactory.booleanLiteral(false);
+    list.insert(1, thirdNode);
+    EngineTestCase.assertSize(3, list);
+    JUnitTestCase.assertSame(firstNode, list[0]);
+    JUnitTestCase.assertSame(thirdNode, list[1]);
+    JUnitTestCase.assertSame(secondNode, list[2]);
+    JUnitTestCase.assertSame(parent, firstNode.parent);
+    JUnitTestCase.assertSame(parent, secondNode.parent);
+    JUnitTestCase.assertSame(parent, thirdNode.parent);
+  }
+  void test_add_negative() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      list.insert(-1, ASTFactory.booleanLiteral(true));
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  void test_add_tooBig() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      list.insert(1, ASTFactory.booleanLiteral(true));
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  void test_addAll() {
+    ASTNode parent = ASTFactory.argumentList([]);
+    List<ASTNode> firstNodes = new List<ASTNode>();
+    ASTNode firstNode = ASTFactory.booleanLiteral(true);
+    ASTNode secondNode = ASTFactory.booleanLiteral(false);
+    firstNodes.add(firstNode);
+    firstNodes.add(secondNode);
+    NodeList<ASTNode> list = new NodeList<ASTNode>(parent);
+    list.addAll(firstNodes);
+    EngineTestCase.assertSize(2, list);
+    JUnitTestCase.assertSame(firstNode, list[0]);
+    JUnitTestCase.assertSame(secondNode, list[1]);
+    JUnitTestCase.assertSame(parent, firstNode.parent);
+    JUnitTestCase.assertSame(parent, secondNode.parent);
+    List<ASTNode> secondNodes = new List<ASTNode>();
+    ASTNode thirdNode = ASTFactory.booleanLiteral(true);
+    ASTNode fourthNode = ASTFactory.booleanLiteral(false);
+    secondNodes.add(thirdNode);
+    secondNodes.add(fourthNode);
+    list.addAll(secondNodes);
+    EngineTestCase.assertSize(4, list);
+    JUnitTestCase.assertSame(firstNode, list[0]);
+    JUnitTestCase.assertSame(secondNode, list[1]);
+    JUnitTestCase.assertSame(thirdNode, list[2]);
+    JUnitTestCase.assertSame(fourthNode, list[3]);
+    JUnitTestCase.assertSame(parent, firstNode.parent);
+    JUnitTestCase.assertSame(parent, secondNode.parent);
+    JUnitTestCase.assertSame(parent, thirdNode.parent);
+    JUnitTestCase.assertSame(parent, fourthNode.parent);
+  }
+  void test_create() {
+    ASTNode owner = ASTFactory.argumentList([]);
+    NodeList<ASTNode> list = NodeList.create(owner);
+    JUnitTestCase.assertNotNull(list);
+    EngineTestCase.assertSize(0, list);
+    JUnitTestCase.assertSame(owner, list.owner);
+  }
+  void test_creation() {
+    ASTNode owner = ASTFactory.argumentList([]);
+    NodeList<ASTNode> list = new NodeList<ASTNode>(owner);
+    JUnitTestCase.assertNotNull(list);
+    EngineTestCase.assertSize(0, list);
+    JUnitTestCase.assertSame(owner, list.owner);
+  }
+  void test_get_negative() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      list[-1];
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  void test_get_tooBig() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      list[1];
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  void test_getBeginToken_empty() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    JUnitTestCase.assertNull(list.beginToken);
+  }
+  void test_getBeginToken_nonEmpty() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    ASTNode node = ASTFactory.parenthesizedExpression(ASTFactory.booleanLiteral(true));
+    list.add(node);
+    JUnitTestCase.assertSame(node.beginToken, list.beginToken);
+  }
+  void test_getEndToken_empty() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    JUnitTestCase.assertNull(list.endToken);
+  }
+  void test_getEndToken_nonEmpty() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    ASTNode node = ASTFactory.parenthesizedExpression(ASTFactory.booleanLiteral(true));
+    list.add(node);
+    JUnitTestCase.assertSame(node.endToken, list.endToken);
+  }
+  void test_remove() {
+    List<ASTNode> nodes = new List<ASTNode>();
+    ASTNode firstNode = ASTFactory.booleanLiteral(true);
+    ASTNode secondNode = ASTFactory.booleanLiteral(false);
+    ASTNode thirdNode = ASTFactory.booleanLiteral(true);
+    nodes.add(firstNode);
+    nodes.add(secondNode);
+    nodes.add(thirdNode);
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    list.addAll(nodes);
+    EngineTestCase.assertSize(3, list);
+    JUnitTestCase.assertSame(secondNode, list.removeAt(1));
+    EngineTestCase.assertSize(2, list);
+    JUnitTestCase.assertSame(firstNode, list[0]);
+    JUnitTestCase.assertSame(thirdNode, list[1]);
+  }
+  void test_remove_negative() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      list.removeAt(-1);
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  void test_remove_tooBig() {
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      list.removeAt(1);
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  void test_set() {
+    List<ASTNode> nodes = new List<ASTNode>();
+    ASTNode firstNode = ASTFactory.booleanLiteral(true);
+    ASTNode secondNode = ASTFactory.booleanLiteral(false);
+    ASTNode thirdNode = ASTFactory.booleanLiteral(true);
+    nodes.add(firstNode);
+    nodes.add(secondNode);
+    nodes.add(thirdNode);
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    list.addAll(nodes);
+    EngineTestCase.assertSize(3, list);
+    ASTNode fourthNode = ASTFactory.integer(0);
+    JUnitTestCase.assertSame(secondNode, javaListSet(list, 1, fourthNode));
+    EngineTestCase.assertSize(3, list);
+    JUnitTestCase.assertSame(firstNode, list[0]);
+    JUnitTestCase.assertSame(fourthNode, list[1]);
+    JUnitTestCase.assertSame(thirdNode, list[2]);
+  }
+  void test_set_negative() {
+    ASTNode node = ASTFactory.booleanLiteral(true);
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      javaListSet(list, -1, node);
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  void test_set_tooBig() {
+    ASTNode node = ASTFactory.booleanLiteral(true);
+    NodeList<ASTNode> list = new NodeList<ASTNode>(ASTFactory.argumentList([]));
+    try {
+      javaListSet(list, 1, node);
+      JUnitTestCase.fail("Expected IndexOutOfBoundsException");
+    } on RangeError catch (exception) {
+    }
+  }
+  static dartSuite() {
+    _ut.group('NodeListTest', () {
+      _ut.test('test_add', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_add);
+      });
+      _ut.test('test_addAll', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_addAll);
+      });
+      _ut.test('test_add_negative', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_add_negative);
+      });
+      _ut.test('test_add_tooBig', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_add_tooBig);
+      });
+      _ut.test('test_create', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_create);
+      });
+      _ut.test('test_creation', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_creation);
+      });
+      _ut.test('test_getBeginToken_empty', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_getBeginToken_empty);
+      });
+      _ut.test('test_getBeginToken_nonEmpty', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_getBeginToken_nonEmpty);
+      });
+      _ut.test('test_getEndToken_empty', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_getEndToken_empty);
+      });
+      _ut.test('test_getEndToken_nonEmpty', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_getEndToken_nonEmpty);
+      });
+      _ut.test('test_get_negative', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_get_negative);
+      });
+      _ut.test('test_get_tooBig', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_get_tooBig);
+      });
+      _ut.test('test_remove', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_remove);
+      });
+      _ut.test('test_remove_negative', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_remove_negative);
+      });
+      _ut.test('test_remove_tooBig', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_remove_tooBig);
+      });
+      _ut.test('test_set', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_set);
+      });
+      _ut.test('test_set_negative', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_set_negative);
+      });
+      _ut.test('test_set_tooBig', () {
+        final __test = new NodeListTest();
+        runJUnitTest(__test, __test.test_set_tooBig);
+      });
+    });
+  }
+}
 class ConstantEvaluatorTest extends ParserTestCase {
   void fail_constructor() {
     Object value = getConstantValue("?");
@@ -1384,28 +1648,28 @@
     assertSource("class C {var a;}", ASTFactory.classDeclaration(null, "C", null, null, null, null, [ASTFactory.fieldDeclaration2(false, Keyword.VAR, [ASTFactory.variableDeclaration("a")])]));
   }
   void test_visitClassTypeAlias_abstract() {
-    assertSource("typedef C = abstract S with M1;", ASTFactory.classTypeAlias("C", null, Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), null));
+    assertSource("class C = abstract S with M1;", ASTFactory.classTypeAlias("C", null, Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), null));
   }
   void test_visitClassTypeAlias_abstract_implements() {
-    assertSource("typedef C = abstract S with M1 implements I;", ASTFactory.classTypeAlias("C", null, Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
+    assertSource("class C = abstract S with M1 implements I;", ASTFactory.classTypeAlias("C", null, Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
   }
   void test_visitClassTypeAlias_generic() {
-    assertSource("typedef C<E> = S<E> with M1<E>;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), null, ASTFactory.typeName4("S", [ASTFactory.typeName4("E", [])]), ASTFactory.withClause([ASTFactory.typeName4("M1", [ASTFactory.typeName4("E", [])])]), null));
+    assertSource("class C<E> = S<E> with M1<E>;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), null, ASTFactory.typeName4("S", [ASTFactory.typeName4("E", [])]), ASTFactory.withClause([ASTFactory.typeName4("M1", [ASTFactory.typeName4("E", [])])]), null));
   }
   void test_visitClassTypeAlias_implements() {
-    assertSource("typedef C = S with M1 implements I;", ASTFactory.classTypeAlias("C", null, null, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
+    assertSource("class C = S with M1 implements I;", ASTFactory.classTypeAlias("C", null, null, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
   }
   void test_visitClassTypeAlias_minimal() {
-    assertSource("typedef C = S with M1;", ASTFactory.classTypeAlias("C", null, null, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), null));
+    assertSource("class C = S with M1;", ASTFactory.classTypeAlias("C", null, null, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), null));
   }
   void test_visitClassTypeAlias_parameters_abstract() {
-    assertSource("typedef C<E> = abstract S with M1;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), null));
+    assertSource("class C<E> = abstract S with M1;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), null));
   }
   void test_visitClassTypeAlias_parameters_abstract_implements() {
-    assertSource("typedef C<E> = abstract S with M1 implements I;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
+    assertSource("class C<E> = abstract S with M1 implements I;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), Keyword.ABSTRACT, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
   }
   void test_visitClassTypeAlias_parameters_implements() {
-    assertSource("typedef C<E> = S with M1 implements I;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), null, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
+    assertSource("class C<E> = S with M1 implements I;", ASTFactory.classTypeAlias("C", ASTFactory.typeParameterList(["E"]), null, ASTFactory.typeName4("S", []), ASTFactory.withClause([ASTFactory.typeName4("M1", [])]), ASTFactory.implementsClause([ASTFactory.typeName4("I", [])])));
   }
   void test_visitComment() {
     assertSource("", Comment.createBlockComment(<Token> [TokenFactory.token2("/* comment */")]));
@@ -3101,6 +3365,7 @@
   ToSourceVisitorTest.dartSuite();
   BreadthFirstVisitorTest.dartSuite();
   IndexExpressionTest.dartSuite();
+  NodeListTest.dartSuite();
   SimpleIdentifierTest.dartSuite();
   VariableDeclarationTest.dartSuite();
 }
\ No newline at end of file
diff --git a/pkg/analyzer_experimental/test/generated/element_test.dart b/pkg/analyzer_experimental/test/generated/element_test.dart
index c7f2f6a..048e507 100644
--- a/pkg/analyzer_experimental/test/generated/element_test.dart
+++ b/pkg/analyzer_experimental/test/generated/element_test.dart
@@ -114,6 +114,51 @@
     });
   }
 }
+class MultiplyDefinedElementImplTest extends EngineTestCase {
+  void test_fromElements_conflicting() {
+    Element firstElement = ElementFactory.localVariableElement2("xx");
+    Element secondElement = ElementFactory.localVariableElement2("yy");
+    Element result = MultiplyDefinedElementImpl.fromElements(null, firstElement, secondElement);
+    EngineTestCase.assertInstanceOf(MultiplyDefinedElement, result);
+    List<Element> elements = ((result as MultiplyDefinedElement)).conflictingElements;
+    EngineTestCase.assertLength(2, elements);
+    for (int i = 0; i < elements.length; i++) {
+      EngineTestCase.assertInstanceOf(LocalVariableElement, elements[i]);
+    }
+  }
+  void test_fromElements_multiple() {
+    Element firstElement = ElementFactory.localVariableElement2("xx");
+    Element secondElement = ElementFactory.localVariableElement2("yy");
+    Element thirdElement = ElementFactory.localVariableElement2("zz");
+    Element result = MultiplyDefinedElementImpl.fromElements(null, MultiplyDefinedElementImpl.fromElements(null, firstElement, secondElement), thirdElement);
+    EngineTestCase.assertInstanceOf(MultiplyDefinedElement, result);
+    List<Element> elements = ((result as MultiplyDefinedElement)).conflictingElements;
+    EngineTestCase.assertLength(3, elements);
+    for (int i = 0; i < elements.length; i++) {
+      EngineTestCase.assertInstanceOf(LocalVariableElement, elements[i]);
+    }
+  }
+  void test_fromElements_nonConflicting() {
+    Element element = ElementFactory.localVariableElement2("xx");
+    JUnitTestCase.assertSame(element, MultiplyDefinedElementImpl.fromElements(null, element, element));
+  }
+  static dartSuite() {
+    _ut.group('MultiplyDefinedElementImplTest', () {
+      _ut.test('test_fromElements_conflicting', () {
+        final __test = new MultiplyDefinedElementImplTest();
+        runJUnitTest(__test, __test.test_fromElements_conflicting);
+      });
+      _ut.test('test_fromElements_multiple', () {
+        final __test = new MultiplyDefinedElementImplTest();
+        runJUnitTest(__test, __test.test_fromElements_multiple);
+      });
+      _ut.test('test_fromElements_nonConflicting', () {
+        final __test = new MultiplyDefinedElementImplTest();
+        runJUnitTest(__test, __test.test_fromElements_nonConflicting);
+      });
+    });
+  }
+}
 class LibraryElementImplTest extends EngineTestCase {
   void test_creation() {
     JUnitTestCase.assertNotNull(new LibraryElementImpl(createAnalysisContext(), ASTFactory.libraryIdentifier2(["l"])));
@@ -205,16 +250,6 @@
   }
 }
 class TypeParameterTypeImplTest extends EngineTestCase {
-  void fail_isMoreSpecificThan_typeArguments_object() {
-    TypeParameterElementImpl element = new TypeParameterElementImpl(ASTFactory.identifier3("E"));
-    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
-    JUnitTestCase.assertTrue(type.isMoreSpecificThan(ElementFactory.object.type));
-  }
-  void fail_isMoreSpecificThan_typeArguments_self() {
-    TypeParameterElementImpl element = new TypeParameterElementImpl(ASTFactory.identifier3("E"));
-    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
-    JUnitTestCase.assertTrue(type.isMoreSpecificThan(type));
-  }
   void test_creation() {
     JUnitTestCase.assertNotNull(new TypeParameterTypeImpl(new TypeParameterElementImpl(ASTFactory.identifier3("E"))));
   }
@@ -223,6 +258,56 @@
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
     JUnitTestCase.assertEquals(element, type.element);
   }
+  void test_isMoreSpecificThan_typeArguments_bottom() {
+    TypeParameterElementImpl element = new TypeParameterElementImpl(ASTFactory.identifier3("E"));
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    JUnitTestCase.assertTrue(type.isMoreSpecificThan(BottomTypeImpl.instance));
+  }
+  void test_isMoreSpecificThan_typeArguments_dynamic() {
+    TypeParameterElementImpl element = new TypeParameterElementImpl(ASTFactory.identifier3("E"));
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    JUnitTestCase.assertTrue(type.isMoreSpecificThan(DynamicTypeImpl.instance));
+  }
+  void test_isMoreSpecificThan_typeArguments_object() {
+    TypeParameterElementImpl element = new TypeParameterElementImpl(ASTFactory.identifier3("E"));
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    JUnitTestCase.assertTrue(type.isMoreSpecificThan(ElementFactory.object.type));
+  }
+  void test_isMoreSpecificThan_typeArguments_resursive() {
+    ClassElementImpl classS = ElementFactory.classElement2("A", []);
+    TypeParameterElementImpl typeParameterU = new TypeParameterElementImpl(ASTFactory.identifier3("U"));
+    TypeParameterTypeImpl typeParameterTypeU = new TypeParameterTypeImpl(typeParameterU);
+    TypeParameterElementImpl typeParameterT = new TypeParameterElementImpl(ASTFactory.identifier3("T"));
+    TypeParameterTypeImpl typeParameterTypeT = new TypeParameterTypeImpl(typeParameterT);
+    typeParameterT.bound = typeParameterTypeU;
+    typeParameterU.bound = typeParameterTypeU;
+    JUnitTestCase.assertFalse(typeParameterTypeT.isMoreSpecificThan(classS.type));
+  }
+  void test_isMoreSpecificThan_typeArguments_self() {
+    TypeParameterElementImpl element = new TypeParameterElementImpl(ASTFactory.identifier3("E"));
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    JUnitTestCase.assertTrue(type.isMoreSpecificThan(type));
+  }
+  void test_isMoreSpecificThan_typeArguments_transitivity_interfaceTypes() {
+    ClassElement classA = ElementFactory.classElement2("A", []);
+    ClassElement classB = ElementFactory.classElement("B", classA.type, []);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    TypeParameterElementImpl typeParameterT = new TypeParameterElementImpl(ASTFactory.identifier3("T"));
+    typeParameterT.bound = typeB;
+    TypeParameterTypeImpl typeParameterTypeT = new TypeParameterTypeImpl(typeParameterT);
+    JUnitTestCase.assertTrue(typeParameterTypeT.isMoreSpecificThan(typeA));
+  }
+  void test_isMoreSpecificThan_typeArguments_transitivity_typeParameters() {
+    ClassElementImpl classS = ElementFactory.classElement2("A", []);
+    TypeParameterElementImpl typeParameterU = new TypeParameterElementImpl(ASTFactory.identifier3("U"));
+    typeParameterU.bound = classS.type;
+    TypeParameterTypeImpl typeParameterTypeU = new TypeParameterTypeImpl(typeParameterU);
+    TypeParameterElementImpl typeParameterT = new TypeParameterElementImpl(ASTFactory.identifier3("T"));
+    typeParameterT.bound = typeParameterTypeU;
+    TypeParameterTypeImpl typeParameterTypeT = new TypeParameterTypeImpl(typeParameterT);
+    JUnitTestCase.assertTrue(typeParameterTypeT.isMoreSpecificThan(classS.type));
+  }
   void test_isMoreSpecificThan_typeArguments_upperBound() {
     ClassElementImpl classS = ElementFactory.classElement2("A", []);
     TypeParameterElementImpl typeParameterT = new TypeParameterElementImpl(ASTFactory.identifier3("T"));
@@ -253,6 +338,34 @@
         final __test = new TypeParameterTypeImplTest();
         runJUnitTest(__test, __test.test_getElement);
       });
+      _ut.test('test_isMoreSpecificThan_typeArguments_bottom', () {
+        final __test = new TypeParameterTypeImplTest();
+        runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_bottom);
+      });
+      _ut.test('test_isMoreSpecificThan_typeArguments_dynamic', () {
+        final __test = new TypeParameterTypeImplTest();
+        runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_dynamic);
+      });
+      _ut.test('test_isMoreSpecificThan_typeArguments_object', () {
+        final __test = new TypeParameterTypeImplTest();
+        runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_object);
+      });
+      _ut.test('test_isMoreSpecificThan_typeArguments_resursive', () {
+        final __test = new TypeParameterTypeImplTest();
+        runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_resursive);
+      });
+      _ut.test('test_isMoreSpecificThan_typeArguments_self', () {
+        final __test = new TypeParameterTypeImplTest();
+        runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_self);
+      });
+      _ut.test('test_isMoreSpecificThan_typeArguments_transitivity_interfaceTypes', () {
+        final __test = new TypeParameterTypeImplTest();
+        runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_transitivity_interfaceTypes);
+      });
+      _ut.test('test_isMoreSpecificThan_typeArguments_transitivity_typeParameters', () {
+        final __test = new TypeParameterTypeImplTest();
+        runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_transitivity_typeParameters);
+      });
       _ut.test('test_isMoreSpecificThan_typeArguments_upperBound', () {
         final __test = new TypeParameterTypeImplTest();
         runJUnitTest(__test, __test.test_isMoreSpecificThan_typeArguments_upperBound);
@@ -996,11 +1109,13 @@
     JUnitTestCase.assertFalse(typeA.isSubtypeOf(typeC));
   }
   void test_isSubtypeOf_typeArguments() {
+    Type2 dynamicType = DynamicTypeImpl.instance;
     ClassElement classA = ElementFactory.classElement2("A", ["E"]);
     ClassElement classI = ElementFactory.classElement2("I", []);
     ClassElement classJ = ElementFactory.classElement("J", classI.type, []);
     ClassElement classK = ElementFactory.classElement2("K", []);
     InterfaceType typeA = classA.type;
+    InterfaceType typeA_dynamic = typeA.substitute4(<Type2> [dynamicType]);
     InterfaceTypeImpl typeAI = new InterfaceTypeImpl.con1(classA);
     InterfaceTypeImpl typeAJ = new InterfaceTypeImpl.con1(classA);
     InterfaceTypeImpl typeAK = new InterfaceTypeImpl.con1(classA);
@@ -1010,10 +1125,10 @@
     JUnitTestCase.assertTrue(typeAJ.isSubtypeOf(typeAI));
     JUnitTestCase.assertFalse(typeAI.isSubtypeOf(typeAJ));
     JUnitTestCase.assertTrue(typeAI.isSubtypeOf(typeAI));
-    JUnitTestCase.assertTrue(typeA.isSubtypeOf(typeAI));
-    JUnitTestCase.assertTrue(typeA.isSubtypeOf(typeAJ));
-    JUnitTestCase.assertTrue(typeAI.isSubtypeOf(typeA));
-    JUnitTestCase.assertTrue(typeAJ.isSubtypeOf(typeA));
+    JUnitTestCase.assertTrue(typeA_dynamic.isSubtypeOf(typeAI));
+    JUnitTestCase.assertTrue(typeA_dynamic.isSubtypeOf(typeAJ));
+    JUnitTestCase.assertTrue(typeAI.isSubtypeOf(typeA_dynamic));
+    JUnitTestCase.assertTrue(typeAJ.isSubtypeOf(typeA_dynamic));
     JUnitTestCase.assertFalse(typeAI.isSubtypeOf(typeAK));
     JUnitTestCase.assertFalse(typeAK.isSubtypeOf(typeAI));
   }
@@ -2859,4 +2974,5 @@
   ElementLocationImplTest.dartSuite();
   ElementImplTest.dartSuite();
   LibraryElementImplTest.dartSuite();
+  MultiplyDefinedElementImplTest.dartSuite();
 }
\ No newline at end of file
diff --git a/pkg/analyzer_experimental/test/generated/parser_test.dart b/pkg/analyzer_experimental/test/generated/parser_test.dart
index b2dcc68..6835d17 100644
--- a/pkg/analyzer_experimental/test/generated/parser_test.dart
+++ b/pkg/analyzer_experimental/test/generated/parser_test.dart
@@ -642,6 +642,28 @@
     JUnitTestCase.assertNotNull(declaration.rightBracket);
     JUnitTestCase.assertNull(declaration.typeParameters);
   }
+  void test_parseClassDeclaration_typeAlias_implementsC() {
+    ClassTypeAlias typeAlias = ParserTestCase.parse("parseClassDeclaration", <Object> [emptyCommentAndMetadata(), null], "class A = Object with B implements C;");
+    JUnitTestCase.assertNotNull(typeAlias.keyword);
+    JUnitTestCase.assertNotNull(typeAlias.name);
+    JUnitTestCase.assertNull(typeAlias.typeParameters);
+    JUnitTestCase.assertNotNull(typeAlias.withClause);
+    JUnitTestCase.assertNotNull(typeAlias.implementsClause);
+    JUnitTestCase.assertNotNull(typeAlias.implementsClause.keyword);
+    JUnitTestCase.assertEquals(1, typeAlias.implementsClause.interfaces.length);
+    JUnitTestCase.assertNotNull(typeAlias.semicolon);
+  }
+  void test_parseClassDeclaration_typeAlias_withB() {
+    ClassTypeAlias typeAlias = ParserTestCase.parse("parseClassDeclaration", <Object> [emptyCommentAndMetadata(), null], "class A = Object with B;");
+    JUnitTestCase.assertNotNull(typeAlias.keyword);
+    JUnitTestCase.assertNotNull(typeAlias.name);
+    JUnitTestCase.assertNull(typeAlias.typeParameters);
+    JUnitTestCase.assertNotNull(typeAlias.withClause);
+    JUnitTestCase.assertNotNull(typeAlias.withClause.withKeyword);
+    JUnitTestCase.assertEquals(1, typeAlias.withClause.mixinTypes.length);
+    JUnitTestCase.assertNull(typeAlias.implementsClause);
+    JUnitTestCase.assertNotNull(typeAlias.semicolon);
+  }
   void test_parseClassDeclaration_typeParameters() {
     ClassDeclaration declaration = ParserTestCase.parse("parseClassDeclaration", <Object> [emptyCommentAndMetadata(), null], "class A<B> {}");
     JUnitTestCase.assertNull(declaration.documentationComment);
@@ -925,7 +947,7 @@
     JUnitTestCase.assertNotNull(constructor.body);
   }
   void test_parseClassTypeAlias() {
-    Token token = TokenFactory.token(Keyword.TYPEDEF);
+    Token token = TokenFactory.token(Keyword.CLASS);
     ClassTypeAlias classTypeAlias = ParserTestCase.parse("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = B;");
     JUnitTestCase.assertNotNull(classTypeAlias.keyword);
     JUnitTestCase.assertEquals("A", classTypeAlias.name.name);
@@ -937,7 +959,7 @@
     JUnitTestCase.assertNotNull(classTypeAlias.semicolon);
   }
   void test_parseClassTypeAlias_abstract() {
-    Token token = TokenFactory.token(Keyword.TYPEDEF);
+    Token token = TokenFactory.token(Keyword.CLASS);
     ClassTypeAlias classTypeAlias = ParserTestCase.parse("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = abstract B;");
     JUnitTestCase.assertNotNull(classTypeAlias.keyword);
     JUnitTestCase.assertEquals("A", classTypeAlias.name.name);
@@ -949,7 +971,7 @@
     JUnitTestCase.assertNotNull(classTypeAlias.semicolon);
   }
   void test_parseClassTypeAlias_implements() {
-    Token token = TokenFactory.token(Keyword.TYPEDEF);
+    Token token = TokenFactory.token(Keyword.CLASS);
     ClassTypeAlias classTypeAlias = ParserTestCase.parse("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = B implements C;");
     JUnitTestCase.assertNotNull(classTypeAlias.keyword);
     JUnitTestCase.assertEquals("A", classTypeAlias.name.name);
@@ -961,7 +983,7 @@
     JUnitTestCase.assertNotNull(classTypeAlias.semicolon);
   }
   void test_parseClassTypeAlias_with() {
-    Token token = TokenFactory.token(Keyword.TYPEDEF);
+    Token token = TokenFactory.token(Keyword.CLASS);
     ClassTypeAlias classTypeAlias = ParserTestCase.parse("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = B with C;");
     JUnitTestCase.assertNotNull(classTypeAlias.keyword);
     JUnitTestCase.assertEquals("A", classTypeAlias.name.name);
@@ -973,7 +995,7 @@
     JUnitTestCase.assertNotNull(classTypeAlias.semicolon);
   }
   void test_parseClassTypeAlias_with_implements() {
-    Token token = TokenFactory.token(Keyword.TYPEDEF);
+    Token token = TokenFactory.token(Keyword.CLASS);
     ClassTypeAlias classTypeAlias = ParserTestCase.parse("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = B with C implements D;");
     JUnitTestCase.assertNotNull(classTypeAlias.keyword);
     JUnitTestCase.assertEquals("A", classTypeAlias.name.name);
@@ -1333,8 +1355,8 @@
     JUnitTestCase.assertNotNull(declaration.functionExpression);
     JUnitTestCase.assertNotNull(declaration.propertyKeyword);
   }
-  void test_parseCompilationUnitMember_typedef_class_abstract() {
-    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "typedef C = abstract S with M;");
+  void test_parseCompilationUnitMember_typeAlias_abstract() {
+    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "class C = abstract S with M;");
     JUnitTestCase.assertNotNull(typeAlias.keyword);
     JUnitTestCase.assertEquals("C", typeAlias.name.name);
     JUnitTestCase.assertNull(typeAlias.typeParameters);
@@ -1345,8 +1367,8 @@
     JUnitTestCase.assertNull(typeAlias.implementsClause);
     JUnitTestCase.assertNotNull(typeAlias.semicolon);
   }
-  void test_parseCompilationUnitMember_typedef_class_generic() {
-    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "typedef C<E> = S<E> with M<E> implements I<E>;");
+  void test_parseCompilationUnitMember_typeAlias_generic() {
+    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "class C<E> = S<E> with M<E> implements I<E>;");
     JUnitTestCase.assertNotNull(typeAlias.keyword);
     JUnitTestCase.assertEquals("C", typeAlias.name.name);
     EngineTestCase.assertSize(1, typeAlias.typeParameters.typeParameters);
@@ -1357,8 +1379,8 @@
     JUnitTestCase.assertNotNull(typeAlias.implementsClause);
     JUnitTestCase.assertNotNull(typeAlias.semicolon);
   }
-  void test_parseCompilationUnitMember_typedef_class_implements() {
-    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "typedef C = S with M implements I;");
+  void test_parseCompilationUnitMember_typeAlias_implements() {
+    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "class C = S with M implements I;");
     JUnitTestCase.assertNotNull(typeAlias.keyword);
     JUnitTestCase.assertEquals("C", typeAlias.name.name);
     JUnitTestCase.assertNull(typeAlias.typeParameters);
@@ -1369,8 +1391,8 @@
     JUnitTestCase.assertNotNull(typeAlias.implementsClause);
     JUnitTestCase.assertNotNull(typeAlias.semicolon);
   }
-  void test_parseCompilationUnitMember_typedef_class_noImplements() {
-    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "typedef C = S with M;");
+  void test_parseCompilationUnitMember_typeAlias_noImplements() {
+    ClassTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "class C = S with M;");
     JUnitTestCase.assertNotNull(typeAlias.keyword);
     JUnitTestCase.assertEquals("C", typeAlias.name.name);
     JUnitTestCase.assertNull(typeAlias.typeParameters);
@@ -1381,7 +1403,7 @@
     JUnitTestCase.assertNull(typeAlias.implementsClause);
     JUnitTestCase.assertNotNull(typeAlias.semicolon);
   }
-  void test_parseCompilationUnitMember_typedef_function() {
+  void test_parseCompilationUnitMember_typedef() {
     FunctionTypeAlias typeAlias = ParserTestCase.parse("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "typedef F();");
     JUnitTestCase.assertEquals("F", typeAlias.name.name);
     EngineTestCase.assertSize(0, typeAlias.parameters.parameters);
@@ -3350,28 +3372,6 @@
     JUnitTestCase.assertNotNull(statement.finallyKeyword);
     JUnitTestCase.assertNotNull(statement.finallyBlock);
   }
-  void test_parseTypeAlias_class_implementsC() {
-    ClassTypeAlias typeAlias = ParserTestCase.parse("parseTypeAlias", <Object> [emptyCommentAndMetadata()], "typedef A = Object with B implements C;");
-    JUnitTestCase.assertNotNull(typeAlias.keyword);
-    JUnitTestCase.assertNotNull(typeAlias.name);
-    JUnitTestCase.assertNull(typeAlias.typeParameters);
-    JUnitTestCase.assertNotNull(typeAlias.withClause);
-    JUnitTestCase.assertNotNull(typeAlias.implementsClause);
-    JUnitTestCase.assertNotNull(typeAlias.implementsClause.keyword);
-    JUnitTestCase.assertEquals(1, typeAlias.implementsClause.interfaces.length);
-    JUnitTestCase.assertNotNull(typeAlias.semicolon);
-  }
-  void test_parseTypeAlias_class_withB() {
-    ClassTypeAlias typeAlias = ParserTestCase.parse("parseTypeAlias", <Object> [emptyCommentAndMetadata()], "typedef A = Object with B;");
-    JUnitTestCase.assertNotNull(typeAlias.keyword);
-    JUnitTestCase.assertNotNull(typeAlias.name);
-    JUnitTestCase.assertNull(typeAlias.typeParameters);
-    JUnitTestCase.assertNotNull(typeAlias.withClause);
-    JUnitTestCase.assertNotNull(typeAlias.withClause.withKeyword);
-    JUnitTestCase.assertEquals(1, typeAlias.withClause.mixinTypes.length);
-    JUnitTestCase.assertNull(typeAlias.implementsClause);
-    JUnitTestCase.assertNotNull(typeAlias.semicolon);
-  }
   void test_parseTypeAlias_function_noParameters() {
     FunctionTypeAlias typeAlias = ParserTestCase.parse("parseTypeAlias", <Object> [emptyCommentAndMetadata()], "typedef bool F();");
     JUnitTestCase.assertNotNull(typeAlias.keyword);
@@ -4365,6 +4365,14 @@
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseClassDeclaration_nonEmpty);
       });
+      _ut.test('test_parseClassDeclaration_typeAlias_implementsC', () {
+        final __test = new SimpleParserTest();
+        runJUnitTest(__test, __test.test_parseClassDeclaration_typeAlias_implementsC);
+      });
+      _ut.test('test_parseClassDeclaration_typeAlias_withB', () {
+        final __test = new SimpleParserTest();
+        runJUnitTest(__test, __test.test_parseClassDeclaration_typeAlias_withB);
+      });
       _ut.test('test_parseClassDeclaration_typeParameters', () {
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseClassDeclaration_typeParameters);
@@ -4645,25 +4653,25 @@
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseCompilationUnitMember_setter_type);
       });
-      _ut.test('test_parseCompilationUnitMember_typedef_class_abstract', () {
+      _ut.test('test_parseCompilationUnitMember_typeAlias_abstract', () {
         final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typedef_class_abstract);
+        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typeAlias_abstract);
       });
-      _ut.test('test_parseCompilationUnitMember_typedef_class_generic', () {
+      _ut.test('test_parseCompilationUnitMember_typeAlias_generic', () {
         final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typedef_class_generic);
+        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typeAlias_generic);
       });
-      _ut.test('test_parseCompilationUnitMember_typedef_class_implements', () {
+      _ut.test('test_parseCompilationUnitMember_typeAlias_implements', () {
         final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typedef_class_implements);
+        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typeAlias_implements);
       });
-      _ut.test('test_parseCompilationUnitMember_typedef_class_noImplements', () {
+      _ut.test('test_parseCompilationUnitMember_typeAlias_noImplements', () {
         final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typedef_class_noImplements);
+        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typeAlias_noImplements);
       });
-      _ut.test('test_parseCompilationUnitMember_typedef_function', () {
+      _ut.test('test_parseCompilationUnitMember_typedef', () {
         final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typedef_function);
+        runJUnitTest(__test, __test.test_parseCompilationUnitMember_typedef);
       });
       _ut.test('test_parseCompilationUnitMember_variable', () {
         final __test = new SimpleParserTest();
@@ -5749,14 +5757,6 @@
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseTryStatement_on_catch_finally);
       });
-      _ut.test('test_parseTypeAlias_class_implementsC', () {
-        final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseTypeAlias_class_implementsC);
-      });
-      _ut.test('test_parseTypeAlias_class_withB', () {
-        final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseTypeAlias_class_withB);
-      });
       _ut.test('test_parseTypeAlias_function_noParameters', () {
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseTypeAlias_function_noParameters);
@@ -6451,7 +6451,7 @@
  * Instances of the class `ASTValidator` are used to validate the correct construction of an
  * AST structure.
  */
-class ASTValidator extends GeneralizingASTVisitor<Object> {
+class ASTValidator extends UnifyingASTVisitor<Object> {
 
   /**
    * A list containing the errors found while traversing the AST structure.
@@ -6980,7 +6980,7 @@
     EngineTestCase.assertInstanceOf(BinaryExpression, expression.leftOperand);
   }
   void test_classTypeAlias_withBody() {
-    ParserTestCase.parseCompilationUnit(EngineTestCase.createSource(["class A {}", "typedef B = Object with A {}"]), [ParserErrorCode.EXPECTED_TOKEN]);
+    ParserTestCase.parseCompilationUnit(EngineTestCase.createSource(["class A {}", "class B = Object with A {}"]), [ParserErrorCode.EXPECTED_TOKEN]);
   }
   void test_conditionalExpression_missingElse() {
     ConditionalExpression expression = ParserTestCase.parse5("parseConditionalExpression", "x ? y :", [ParserErrorCode.MISSING_IDENTIFIER]);
@@ -7599,6 +7599,12 @@
  * that errors are correctly reported, and in some cases, not reported.
  */
 class ErrorParserTest extends ParserTestCase {
+  void fail_deprecatedClassTypeAlias() {
+    ParserTestCase.parseCompilationUnit("typedef C = abstract S with M;", [ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS]);
+  }
+  void fail_deprecatedClassTypeAlias_withGeneric() {
+    ParserTestCase.parseCompilationUnit("typedef C<T> = abstract S<T> with M;", [ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS]);
+  }
   void fail_expectedListOrMapLiteral() {
     TypedLiteral literal = ParserTestCase.parse4("parseListOrMapLiteral", <Object> [null], "1", [ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL]);
     JUnitTestCase.assertTrue(literal.isSynthetic);
@@ -7822,10 +7828,6 @@
   void test_expectedInterpolationIdentifier() {
     ParserTestCase.parse5("parseStringLiteral", "'\$x\$'", [ParserErrorCode.MISSING_IDENTIFIER]);
   }
-  void test_expectedOneListTypeArguments_two() {
-    Expression expression = ParserTestCase.parse5("parsePrimaryExpression", "<int, int>[]", [ParserErrorCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
-    EngineTestCase.assertInstanceOf(ListLiteral, expression);
-  }
   void test_expectedStringLiteral() {
     StringLiteral expression = ParserTestCase.parse5("parseStringLiteral", "1", [ParserErrorCode.EXPECTED_STRING_LITERAL]);
     JUnitTestCase.assertTrue(expression.isSynthetic);
@@ -7838,8 +7840,8 @@
         ParserErrorCode.EXPECTED_TOKEN,
         ParserErrorCode.MISSING_IDENTIFIER]);
   }
-  void test_expectedToken_semicolonAfterTypedef() {
-    Token token = TokenFactory.token(Keyword.TYPEDEF);
+  void test_expectedToken_semicolonAfterClass() {
+    Token token = TokenFactory.token(Keyword.CLASS);
     ParserTestCase.parse4("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = B", [ParserErrorCode.EXPECTED_TOKEN]);
   }
   void test_expectedToken_semicolonMissingAfterExpression() {
@@ -7848,14 +7850,6 @@
   void test_expectedToken_whileMissingInDoStatement() {
     ParserTestCase.parseStatement("do {} (x);", [ParserErrorCode.EXPECTED_TOKEN]);
   }
-  void test_expectedTwoMapTypeArguments_one() {
-    Expression expression = ParserTestCase.parse5("parsePrimaryExpression", "<int>{}", [ParserErrorCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
-    EngineTestCase.assertInstanceOf(MapLiteral, expression);
-  }
-  void test_expectedTwoMapTypeArguments_three() {
-    Expression expression = ParserTestCase.parse5("parsePrimaryExpression", "<int, int, int>{}", [ParserErrorCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
-    EngineTestCase.assertInstanceOf(MapLiteral, expression);
-  }
   void test_expectedTypeName_is() {
     ParserTestCase.parseExpression("x is", [ParserErrorCode.EXPECTED_TYPE_NAME]);
   }
@@ -8635,10 +8629,6 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_expectedInterpolationIdentifier);
       });
-      _ut.test('test_expectedOneListTypeArguments_two', () {
-        final __test = new ErrorParserTest();
-        runJUnitTest(__test, __test.test_expectedOneListTypeArguments_two);
-      });
       _ut.test('test_expectedStringLiteral', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_expectedStringLiteral);
@@ -8651,9 +8641,9 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_expectedToken_parseStatement_afterVoid);
       });
-      _ut.test('test_expectedToken_semicolonAfterTypedef', () {
+      _ut.test('test_expectedToken_semicolonAfterClass', () {
         final __test = new ErrorParserTest();
-        runJUnitTest(__test, __test.test_expectedToken_semicolonAfterTypedef);
+        runJUnitTest(__test, __test.test_expectedToken_semicolonAfterClass);
       });
       _ut.test('test_expectedToken_semicolonMissingAfterExpression', () {
         final __test = new ErrorParserTest();
@@ -8663,14 +8653,6 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_expectedToken_whileMissingInDoStatement);
       });
-      _ut.test('test_expectedTwoMapTypeArguments_one', () {
-        final __test = new ErrorParserTest();
-        runJUnitTest(__test, __test.test_expectedTwoMapTypeArguments_one);
-      });
-      _ut.test('test_expectedTwoMapTypeArguments_three', () {
-        final __test = new ErrorParserTest();
-        runJUnitTest(__test, __test.test_expectedTwoMapTypeArguments_three);
-      });
       _ut.test('test_expectedTypeName_is', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_expectedTypeName_is);
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart
index 8166ad3..9620ea8 100644
--- a/pkg/analyzer_experimental/test/generated/resolver_test.dart
+++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -947,6 +947,21 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_argumentTypeNotAssignable_fieldFormalParameterElement_member() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class ObjectSink<T> {",
+        "  void sink(T object) {",
+        "    new TimestampedObject<T>(object);",
+        "  }",
+        "}",
+        "class TimestampedObject<E> {",
+        "  E object2;",
+        "  TimestampedObject(this.object2);",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_argumentTypeNotAssignable_invocation_functionParameter_generic() {
     Source source = addSource(EngineTestCase.createSource([
         "class A<K> {",
@@ -1389,6 +1404,18 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_expectedOneListTypeArgument() {
+    Source source = addSource(EngineTestCase.createSource(["main() {", "  <int> [];", "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+  void test_expectedTwoMapTypeArguments() {
+    Source source = addSource(EngineTestCase.createSource(["main() {", "  <int, int> {};", "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_exportOfNonLibrary_libraryDeclared() {
     Source source = addSource(EngineTestCase.createSource(["library L;", "export 'lib1.dart';"]));
     addSource2("/lib1.dart", EngineTestCase.createSource(["library lib1;"]));
@@ -1572,6 +1599,22 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_functionWithoutCall() {
+    Source source = addSource(EngineTestCase.createSource([
+        "abstract class A implements Function {",
+        "}",
+        "class B implements A {",
+        "  void call() {}",
+        "}",
+        "class C extends A {",
+        "  void call() {}",
+        "}",
+        "class D extends C {",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_implicitThisReferenceInInitializer_constructorName() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -2042,7 +2085,7 @@
         "  m(a, b) {}",
         "}",
         "class B extends A {",
-        "  m(a) {}",
+        "  m(a, [b]) {}",
         "}"]));
     resolve(source);
     assertNoErrors(source);
@@ -2350,20 +2393,20 @@
     assertNoErrors(source);
     verify([source]);
   }
-  void test_mixinInheritsFromNotObject_classDeclaration_mixTypedef() {
+  void test_mixinInheritsFromNotObject_classDeclaration_mixTypeAlias() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
-        "typedef B = Object with A;",
+        "class B = Object with A;",
         "class C extends Object with B {}"]));
     resolve(source);
     assertNoErrors(source);
     verify([source]);
   }
-  void test_mixinInheritsFromNotObject_typedef_mixTypedef() {
+  void test_mixinInheritsFromNotObject_typedef_mixTypeAlias() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
-        "typedef B = Object with A;",
-        "typedef C = Object with B;"]));
+        "class B = Object with A;",
+        "class C = Object with B;"]));
     resolve(source);
     assertNoErrors(source);
     verify([source]);
@@ -2801,6 +2844,16 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_propagateTypeArgsIntoBounds() {
+    Source source = addSource(EngineTestCase.createSource([
+        "abstract class A<E> {}",
+        "abstract class B<F> implements A<F>{}",
+        "abstract class C<G, H extends A<G>> {}",
+        "class D<I> extends C<I, B<I>> {}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_proxy_annotation_prefixed() {
     Source source = addSource(EngineTestCase.createSource([
         "library L;",
@@ -2926,6 +2979,18 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_redirectToInvalidReturnType() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  A() {}",
+        "}",
+        "class B extends A {",
+        "  factory B() = A;",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_redirectToNonConstConstructor() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -3231,10 +3296,10 @@
     assertNoErrors(source);
     verify([source]);
   }
-  void test_undefinedConstructorInInitializer_implicit_typedef() {
+  void test_undefinedConstructorInInitializer_implicit_typeAlias() {
     Source source = addSource(EngineTestCase.createSource([
         "class M {}",
-        "typedef A = Object with M;",
+        "class A = Object with M;",
         "class B extends A {",
         "  B();",
         "}"]));
@@ -3425,6 +3490,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_argumentTypeNotAssignable_classWithCall_Function);
       });
+      _ut.test('test_argumentTypeNotAssignable_fieldFormalParameterElement_member', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_argumentTypeNotAssignable_fieldFormalParameterElement_member);
+      });
       _ut.test('test_argumentTypeNotAssignable_invocation_functionParameter_generic', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_argumentTypeNotAssignable_invocation_functionParameter_generic);
@@ -3585,6 +3654,14 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_dynamicIdentifier);
       });
+      _ut.test('test_expectedOneListTypeArgument', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_expectedOneListTypeArgument);
+      });
+      _ut.test('test_expectedTwoMapTypeArguments', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_expectedTwoMapTypeArguments);
+      });
       _ut.test('test_exportOfNonLibrary_libraryDeclared', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_exportOfNonLibrary_libraryDeclared);
@@ -3685,6 +3762,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_functionTypeAlias_scope_signature);
       });
+      _ut.test('test_functionWithoutCall', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_functionWithoutCall);
+      });
       _ut.test('test_implicitThisReferenceInInitializer_constructorName', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_implicitThisReferenceInInitializer_constructorName);
@@ -3985,13 +4066,13 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_mixinDeclaresConstructor_factory);
       });
-      _ut.test('test_mixinInheritsFromNotObject_classDeclaration_mixTypedef', () {
+      _ut.test('test_mixinInheritsFromNotObject_classDeclaration_mixTypeAlias', () {
         final __test = new NonErrorResolverTest();
-        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_classDeclaration_mixTypedef);
+        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_classDeclaration_mixTypeAlias);
       });
-      _ut.test('test_mixinInheritsFromNotObject_typedef_mixTypedef', () {
+      _ut.test('test_mixinInheritsFromNotObject_typedef_mixTypeAlias', () {
         final __test = new NonErrorResolverTest();
-        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_typedef_mixTypedef);
+        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_typedef_mixTypeAlias);
       });
       _ut.test('test_multipleSuperInitializers_no', () {
         final __test = new NonErrorResolverTest();
@@ -4165,6 +4246,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_prefixCollidesWithTopLevelMembers);
       });
+      _ut.test('test_propagateTypeArgsIntoBounds', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_propagateTypeArgsIntoBounds);
+      });
       _ut.test('test_proxy_annotation_prefixed', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_proxy_annotation_prefixed);
@@ -4193,6 +4278,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_redirectToInvalidFunctionType);
       });
+      _ut.test('test_redirectToInvalidReturnType', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_redirectToInvalidReturnType);
+      });
       _ut.test('test_redirectToNonConstConstructor', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_redirectToNonConstConstructor);
@@ -4309,9 +4398,9 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_undefinedConstructorInInitializer_implicit);
       });
-      _ut.test('test_undefinedConstructorInInitializer_implicit_typedef', () {
+      _ut.test('test_undefinedConstructorInInitializer_implicit_typeAlias', () {
         final __test = new NonErrorResolverTest();
-        runJUnitTest(__test, __test.test_undefinedConstructorInInitializer_implicit_typedef);
+        runJUnitTest(__test, __test.test_undefinedConstructorInInitializer_implicit_typeAlias);
       });
       _ut.test('test_undefinedConstructorInInitializer_redirecting', () {
         final __test = new NonErrorResolverTest();
@@ -4511,6 +4600,24 @@
     assertErrors(source, [StaticTypeWarningCode.INACCESSIBLE_SETTER]);
     verify([source]);
   }
+  void test_expectedOneListTypeArgument() {
+    Source source = addSource(EngineTestCase.createSource(["main() {", "  <int, int> [];", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
+    verify([source]);
+  }
+  void test_expectedTwoMapTypeArguments_one() {
+    Source source = addSource(EngineTestCase.createSource(["main() {", "  <int> {};", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+    verify([source]);
+  }
+  void test_expectedTwoMapTypeArguments_three() {
+    Source source = addSource(EngineTestCase.createSource(["main() {", "  <int, int, int> {};", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+    verify([source]);
+  }
   void test_inconsistentMethodInheritance_paramCount() {
     Source source = addSource(EngineTestCase.createSource([
         "abstract class A {",
@@ -4865,7 +4972,7 @@
         "class B {}",
         "class C {}",
         "class G<E extends A> {}",
-        "typedef D = G<B> with C;"]));
+        "class D = G<B> with C;"]));
     resolve(source);
     assertErrors(source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -5040,6 +5147,12 @@
     assertErrors(source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
   }
+  void test_typeParameterSupertypeOfItsBound() {
+    Source source = addSource(EngineTestCase.createSource(["class A<T extends T> {", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND]);
+    verify([source]);
+  }
   void test_undefinedGetter() {
     Source source = addSource(EngineTestCase.createSource(["class T {}", "f(T e) { return e.m; }"]));
     resolve(source);
@@ -5082,6 +5195,18 @@
     resolve(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
+  void test_undefinedMethod_private() {
+    addSource2("/lib.dart", EngineTestCase.createSource(["library lib;", "class A {", "  _foo() {}", "}"]));
+    Source source = addSource(EngineTestCase.createSource([
+        "import 'lib.dart';",
+        "class B extends A {",
+        "  test() {",
+        "    _foo();",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
+  }
   void test_undefinedOperator_indexBoth() {
     Source source = addSource(EngineTestCase.createSource(["class A {}", "f(A a) {", "  a[0]++;", "}"]));
     resolve(source);
@@ -5211,6 +5336,18 @@
   }
   static dartSuite() {
     _ut.group('StaticTypeWarningCodeTest', () {
+      _ut.test('test_expectedOneListTypeArgument', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_expectedOneListTypeArgument);
+      });
+      _ut.test('test_expectedTwoMapTypeArguments_one', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_expectedTwoMapTypeArguments_one);
+      });
+      _ut.test('test_expectedTwoMapTypeArguments_three', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_expectedTwoMapTypeArguments_three);
+      });
       _ut.test('test_inconsistentMethodInheritance_paramCount', () {
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_inconsistentMethodInheritance_paramCount);
@@ -5439,6 +5576,10 @@
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_typeArgumentNotMatchingBounds_with);
       });
+      _ut.test('test_typeParameterSupertypeOfItsBound', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_typeParameterSupertypeOfItsBound);
+      });
       _ut.test('test_undefinedGetter', () {
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedGetter);
@@ -5459,6 +5600,10 @@
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedMethod_ignoreTypePropagation);
       });
+      _ut.test('test_undefinedMethod_private', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_undefinedMethod_private);
+      });
       _ut.test('test_undefinedOperator_indexBoth', () {
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedOperator_indexBoth);
@@ -5924,6 +6069,17 @@
     resolve(source);
     assertErrors(source, [HintCode.UNDEFINED_METHOD]);
   }
+  void test_undefinedOperator_binaryExpression() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a + 1;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
+  }
   void test_undefinedOperator_indexBoth() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
@@ -5957,17 +6113,6 @@
     resolve(source);
     assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
   }
-  void test_undefinedOperator_plus() {
-    Source source = addSource(EngineTestCase.createSource([
-        "class A {}",
-        "f(var a) {",
-        "  if(a is A) {",
-        "    a + 1;",
-        "  }",
-        "}"]));
-    resolve(source);
-    assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
-  }
   void test_undefinedOperator_postfixExpression() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
@@ -6274,6 +6419,10 @@
         final __test = new HintCodeTest();
         runJUnitTest(__test, __test.test_undefinedMethod_assignmentExpression);
       });
+      _ut.test('test_undefinedOperator_binaryExpression', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_binaryExpression);
+      });
       _ut.test('test_undefinedOperator_indexBoth', () {
         final __test = new HintCodeTest();
         runJUnitTest(__test, __test.test_undefinedOperator_indexBoth);
@@ -6286,10 +6435,6 @@
         final __test = new HintCodeTest();
         runJUnitTest(__test, __test.test_undefinedOperator_indexSetter);
       });
-      _ut.test('test_undefinedOperator_plus', () {
-        final __test = new HintCodeTest();
-        runJUnitTest(__test, __test.test_undefinedOperator_plus);
-      });
       _ut.test('test_undefinedOperator_postfixExpression', () {
         final __test = new HintCodeTest();
         runJUnitTest(__test, __test.test_undefinedOperator_postfixExpression);
@@ -7741,6 +7886,12 @@
         CompileTimeErrorCode.ARGUMENT_DEFINITION_TEST_NON_PARAMETER]);
     verify([source]);
   }
+  void test_builtInIdentifierAsMixinName_classTypeAlias() {
+    Source source = addSource(EngineTestCase.createSource(["class A {}", "class B {}", "class as = A with B;"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]);
+    verify([source]);
+  }
   void test_builtInIdentifierAsType_formalParameter_field() {
     Source source = addSource(EngineTestCase.createSource(["class A {", "  var x;", "  A(static this.x);", "}"]));
     resolve(source);
@@ -7759,12 +7910,6 @@
     assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     verify([source]);
   }
-  void test_builtInIdentifierAsTypedefName_classTypeAlias() {
-    Source source = addSource(EngineTestCase.createSource(["class A {}", "class B {}", "typedef as = A with B;"]));
-    resolve(source);
-    assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]);
-    verify([source]);
-  }
   void test_builtInIdentifierAsTypedefName_functionTypeAlias() {
     Source source = addSource(EngineTestCase.createSource(["typedef bool as();"]));
     resolve(source);
@@ -7864,6 +8009,42 @@
     assertErrors(source, [CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER]);
     verify([source]);
   }
+  void test_conflictingTypeVariableAndClass() {
+    Source source = addSource(EngineTestCase.createSource(["class T<T> {", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS]);
+    verify([source]);
+  }
+  void test_conflictingTypeVariableAndMember_field() {
+    Source source = addSource(EngineTestCase.createSource(["class A<T> {", "  var T;", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+    verify([source]);
+  }
+  void test_conflictingTypeVariableAndMember_getter() {
+    Source source = addSource(EngineTestCase.createSource(["class A<T> {", "  get T => null;", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+    verify([source]);
+  }
+  void test_conflictingTypeVariableAndMember_method() {
+    Source source = addSource(EngineTestCase.createSource(["class A<T> {", "  T() {}", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+    verify([source]);
+  }
+  void test_conflictingTypeVariableAndMember_method_static() {
+    Source source = addSource(EngineTestCase.createSource(["class A<T> {", "  static T() {}", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+    verify([source]);
+  }
+  void test_conflictingTypeVariableAndMember_setter() {
+    Source source = addSource(EngineTestCase.createSource(["class A<T> {", "  set T(x) {}", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
+    verify([source]);
+  }
   void test_constConstructorWithNonConstSuper_explicit() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -8067,6 +8248,35 @@
     assertErrors(source, [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
     verify([source]);
   }
+  void test_constMapKeyTypeImplementsEquals_direct() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  const A();",
+        "  operator ==(other) => false;",
+        "}",
+        "main() {",
+        "  const {const A() : 0};",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+    verify([source]);
+  }
+  void test_constMapKeyTypeImplementsEquals_super() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  const A();",
+        "  operator ==(other) => false;",
+        "}",
+        "class B extends A {",
+        "  const B();",
+        "}",
+        "main() {",
+        "  const {const B() : 0};",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
+    verify([source]);
+  }
   void test_constWithInvalidTypeParameters() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -8685,8 +8895,8 @@
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
     verify([source]);
   }
-  void test_implementsNonClass_typedef() {
-    Source source = addSource(EngineTestCase.createSource(["class A {}", "int B;", "typedef C = A implements B;"]));
+  void test_implementsNonClass_typeAlias() {
+    Source source = addSource(EngineTestCase.createSource(["class A {}", "int B;", "class C = A implements B;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
     verify([source]);
@@ -9169,12 +9379,8 @@
     assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
     verify([source]);
   }
-  void test_mixinDeclaresConstructor_typedef() {
-    Source source = addSource(EngineTestCase.createSource([
-        "class A {",
-        "  A() {}",
-        "}",
-        "typedef B = Object with A;"]));
+  void test_mixinDeclaresConstructor_typeAlias() {
+    Source source = addSource(EngineTestCase.createSource(["class A {", "  A() {}", "}", "class B = Object with A;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
     verify([source]);
@@ -9197,20 +9403,20 @@
     assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verify([source]);
   }
-  void test_mixinInheritsFromNotObject_typedef_extends() {
+  void test_mixinInheritsFromNotObject_typeAlias_extends() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
         "class B extends A {}",
-        "typedef C = Object with B;"]));
+        "class C = Object with B;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verify([source]);
   }
-  void test_mixinInheritsFromNotObject_typedef_with() {
+  void test_mixinInheritsFromNotObject_typeAlias_with() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
         "class B extends Object with A {}",
-        "typedef C = Object with B;"]));
+        "class C = Object with B;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verify([source]);
@@ -9257,8 +9463,8 @@
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
     verify([source]);
   }
-  void test_mixinOfNonClass_typedef() {
-    Source source = addSource(EngineTestCase.createSource(["class A {}", "int B;", "typedef C = A with B;"]));
+  void test_mixinOfNonClass_typeAlias() {
+    Source source = addSource(EngineTestCase.createSource(["class A {}", "int B;", "class C = A with B;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
     verify([source]);
@@ -9279,8 +9485,8 @@
     assertErrors(source, [CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS]);
     verify([source]);
   }
-  void test_mixinWithNonClassSuperclass_typedef() {
-    Source source = addSource(EngineTestCase.createSource(["int A;", "class B {}", "typedef C = A with B;"]));
+  void test_mixinWithNonClassSuperclass_typeAlias() {
+    Source source = addSource(EngineTestCase.createSource(["int A;", "class B {}", "class C = A with B;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS]);
     verify([source]);
@@ -9832,11 +10038,11 @@
     assertErrors(source, [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]);
     verify([source]);
   }
-  void test_recursiveInterfaceInheritanceBaseCaseImplements_typedef() {
+  void test_recursiveInterfaceInheritanceBaseCaseImplements_typeAlias() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
         "class M {}",
-        "typedef B = A with M implements B;"]));
+        "class B = A with M implements B;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]);
     verify([source]);
@@ -10038,15 +10244,15 @@
     verify([source]);
   }
   void test_typeAliasCannotRereferenceItself_mixin_direct() {
-    Source source = addSource(EngineTestCase.createSource(["typedef M = Object with M;"]));
+    Source source = addSource(EngineTestCase.createSource(["class M = Object with M;"]));
     resolve(source);
     assertErrors(source, [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
     verify([source]);
   }
   void test_typeAliasCannotRereferenceItself_mixin_indirect() {
     Source source = addSource(EngineTestCase.createSource([
-        "typedef M1 = Object with M2;",
-        "typedef M2 = Object with M1;"]));
+        "class M1 = Object with M2;",
+        "class M2 = Object with M1;"]));
     resolve(source);
     assertErrors(source, [
         CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
@@ -10313,6 +10519,10 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_argumentDefinitionTestNonParameter);
       });
+      _ut.test('test_builtInIdentifierAsMixinName_classTypeAlias', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_builtInIdentifierAsMixinName_classTypeAlias);
+      });
       _ut.test('test_builtInIdentifierAsTypeName', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_builtInIdentifierAsTypeName);
@@ -10333,10 +10543,6 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_builtInIdentifierAsType_variableDeclaration);
       });
-      _ut.test('test_builtInIdentifierAsTypedefName_classTypeAlias', () {
-        final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_builtInIdentifierAsTypedefName_classTypeAlias);
-      });
       _ut.test('test_builtInIdentifierAsTypedefName_functionTypeAlias', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_builtInIdentifierAsTypedefName_functionTypeAlias);
@@ -10369,6 +10575,30 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_conflictingGetterAndMethod_method_getter);
       });
+      _ut.test('test_conflictingTypeVariableAndClass', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_conflictingTypeVariableAndClass);
+      });
+      _ut.test('test_conflictingTypeVariableAndMember_field', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_conflictingTypeVariableAndMember_field);
+      });
+      _ut.test('test_conflictingTypeVariableAndMember_getter', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_conflictingTypeVariableAndMember_getter);
+      });
+      _ut.test('test_conflictingTypeVariableAndMember_method', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_conflictingTypeVariableAndMember_method);
+      });
+      _ut.test('test_conflictingTypeVariableAndMember_method_static', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_conflictingTypeVariableAndMember_method_static);
+      });
+      _ut.test('test_conflictingTypeVariableAndMember_setter', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_conflictingTypeVariableAndMember_setter);
+      });
       _ut.test('test_constConstructorWithNonConstSuper_explicit', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_constConstructorWithNonConstSuper_explicit);
@@ -10473,6 +10703,14 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_constInstanceField);
       });
+      _ut.test('test_constMapKeyTypeImplementsEquals_direct', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_constMapKeyTypeImplementsEquals_direct);
+      });
+      _ut.test('test_constMapKeyTypeImplementsEquals_super', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_constMapKeyTypeImplementsEquals_super);
+      });
       _ut.test('test_constWithInvalidTypeParameters', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_constWithInvalidTypeParameters);
@@ -10753,9 +10991,9 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_implementsNonClass_class);
       });
-      _ut.test('test_implementsNonClass_typedef', () {
+      _ut.test('test_implementsNonClass_typeAlias', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_implementsNonClass_typedef);
+        runJUnitTest(__test, __test.test_implementsNonClass_typeAlias);
       });
       _ut.test('test_implementsRepeated', () {
         final __test = new CompileTimeErrorCodeTest();
@@ -11001,9 +11239,9 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_mixinDeclaresConstructor_classDeclaration);
       });
-      _ut.test('test_mixinDeclaresConstructor_typedef', () {
+      _ut.test('test_mixinDeclaresConstructor_typeAlias', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_mixinDeclaresConstructor_typedef);
+        runJUnitTest(__test, __test.test_mixinDeclaresConstructor_typeAlias);
       });
       _ut.test('test_mixinInheritsFromNotObject_classDeclaration_extends', () {
         final __test = new CompileTimeErrorCodeTest();
@@ -11013,13 +11251,13 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_classDeclaration_with);
       });
-      _ut.test('test_mixinInheritsFromNotObject_typedef_extends', () {
+      _ut.test('test_mixinInheritsFromNotObject_typeAlias_extends', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_typedef_extends);
+        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_typeAlias_extends);
       });
-      _ut.test('test_mixinInheritsFromNotObject_typedef_with', () {
+      _ut.test('test_mixinInheritsFromNotObject_typeAlias_with', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_typedef_with);
+        runJUnitTest(__test, __test.test_mixinInheritsFromNotObject_typeAlias_with);
       });
       _ut.test('test_mixinOfDisallowedClass_Null', () {
         final __test = new CompileTimeErrorCodeTest();
@@ -11049,9 +11287,9 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_mixinOfNonClass_class);
       });
-      _ut.test('test_mixinOfNonClass_typedef', () {
+      _ut.test('test_mixinOfNonClass_typeAlias', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_mixinOfNonClass_typedef);
+        runJUnitTest(__test, __test.test_mixinOfNonClass_typeAlias);
       });
       _ut.test('test_mixinReferencesSuper', () {
         final __test = new CompileTimeErrorCodeTest();
@@ -11061,9 +11299,9 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_mixinWithNonClassSuperclass_class);
       });
-      _ut.test('test_mixinWithNonClassSuperclass_typedef', () {
+      _ut.test('test_mixinWithNonClassSuperclass_typeAlias', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_mixinWithNonClassSuperclass_typedef);
+        runJUnitTest(__test, __test.test_mixinWithNonClassSuperclass_typeAlias);
       });
       _ut.test('test_multipleRedirectingConstructorInvocations', () {
         final __test = new CompileTimeErrorCodeTest();
@@ -11281,9 +11519,9 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_recursiveInterfaceInheritanceBaseCaseImplements);
       });
-      _ut.test('test_recursiveInterfaceInheritanceBaseCaseImplements_typedef', () {
+      _ut.test('test_recursiveInterfaceInheritanceBaseCaseImplements_typeAlias', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_recursiveInterfaceInheritanceBaseCaseImplements_typedef);
+        runJUnitTest(__test, __test.test_recursiveInterfaceInheritanceBaseCaseImplements_typeAlias);
       });
       _ut.test('test_recursiveInterfaceInheritance_extends', () {
         final __test = new CompileTimeErrorCodeTest();
@@ -12801,17 +13039,6 @@
   }
 }
 class StaticWarningCodeTest extends ResolverTestCase {
-  void fail_argumentTypeNotAssignable_invocation_functionParameter_generic() {
-    Source source = addSource(EngineTestCase.createSource([
-        "class A<K, V> {",
-        "  m(f(K k), V v) {",
-        "    f(v);",
-        "  }",
-        "}"]));
-    resolve(source);
-    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
   void fail_commentReferenceConstructorNotVisible() {
     Source source = addSource(EngineTestCase.createSource([]));
     resolve(source);
@@ -13148,6 +13375,17 @@
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
+  void test_argumentTypeNotAssignable_invocation_functionParameter_generic() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A<K, V> {",
+        "  m(f(K k), V v) {",
+        "    f(v);",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
   void test_argumentTypeNotAssignable_invocation_functionTypes_optional() {
     Source source = addSource(EngineTestCase.createSource([
         "void acceptFunNumOptBool(void funNumOptBool([bool b])) {}",
@@ -13267,6 +13505,21 @@
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
     verify([source]);
   }
+  void test_assignmentToFinal_excludedSetter() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  var v;",
+        "}",
+        "class B extends A {",
+        "  final v = 0;",
+        "}",
+        "main() {",
+        "  new B().v = 1;",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
+    verify([source]);
+  }
   void test_assignmentToFinal_instanceVariable() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -13369,6 +13622,16 @@
     assertErrors(source, [StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER]);
     verify([source]);
   }
+  void test_conflictingDartImport() {
+    Source source = addSource(EngineTestCase.createSource([
+        "import 'lib.dart';",
+        "import 'dart:async';",
+        "Future f = null;",
+        "Stream s;"]));
+    addSource2("/lib.dart", EngineTestCase.createSource(["library lib;", "class Future {}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.CONFLICTING_DART_IMPORT]);
+  }
   void test_conflictingInstanceGetterAndSuperclassMember_direct_field() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -13613,6 +13876,32 @@
     assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
     verify([source]);
   }
+  void test_functionWithoutCall_direct() {
+    Source source = addSource(EngineTestCase.createSource(["class A implements Function {", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
+  void test_functionWithoutCall_indirect_extends() {
+    Source source = addSource(EngineTestCase.createSource([
+        "abstract class A implements Function {",
+        "}",
+        "class B extends A {",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
+  void test_functionWithoutCall_indirect_implements() {
+    Source source = addSource(EngineTestCase.createSource([
+        "abstract class A implements Function {",
+        "}",
+        "class B implements A {",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
   void test_importDuplicatedLibraryName() {
     Source source = addSource(EngineTestCase.createSource([
         "library test;",
@@ -13931,7 +14220,7 @@
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_NAMED]);
     verify([source]);
   }
-  void test_invalidOverridePositional() {
+  void test_invalidOverridePositional_optional() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
         "  m([a, b]) {}",
@@ -13943,6 +14232,30 @@
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]);
     verify([source]);
   }
+  void test_invalidOverridePositional_optionalAndRequired() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  m(a, b, [c, d]) {}",
+        "}",
+        "class B extends A {",
+        "  m(a, b, [c]) {}",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]);
+    verify([source]);
+  }
+  void test_invalidOverridePositional_optionalAndRequired2() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  m(a, b, [c, d]) {}",
+        "}",
+        "class B extends A {",
+        "  m(a, [c, d]) {}",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]);
+    verify([source]);
+  }
   void test_invalidOverrideRequired() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -14168,6 +14481,18 @@
     assertErrors(source, [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
   }
+  void test_nonAbstractClassInheritsAbstractMemberOne_setter_excluded() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  final int x = 0;",
+        "}",
+        "class B implements A {",
+        "  int get x => 42;",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
+    verify([source]);
+  }
   void test_nonAbstractClassInheritsAbstractMemberOne_setter_fromInterface() {
     Source source = addSource(EngineTestCase.createSource([
         "class I {",
@@ -14548,6 +14873,30 @@
     resolve(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
+  void test_undefinedIdentifier_private_getter() {
+    addSource2("/lib.dart", EngineTestCase.createSource(["library lib;", "class A {", "  var _foo;", "}"]));
+    Source source = addSource(EngineTestCase.createSource([
+        "import 'lib.dart';",
+        "class B extends A {",
+        "  test() {",
+        "    var v = _foo;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+  }
+  void test_undefinedIdentifier_private_setter() {
+    addSource2("/lib.dart", EngineTestCase.createSource(["library lib;", "class A {", "  var _foo;", "}"]));
+    Source source = addSource(EngineTestCase.createSource([
+        "import 'lib.dart';",
+        "class B extends A {",
+        "  test() {",
+        "    _foo = 42;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+  }
   void test_undefinedNamedParameter() {
     Source source = addSource(EngineTestCase.createSource(["f({a, b}) {}", "main() {", "  f(c: 1);", "}"]));
     resolve(source);
@@ -14650,6 +14999,10 @@
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_argumentTypeNotAssignable_invocation_functionParameter);
       });
+      _ut.test('test_argumentTypeNotAssignable_invocation_functionParameter_generic', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_argumentTypeNotAssignable_invocation_functionParameter_generic);
+      });
       _ut.test('test_argumentTypeNotAssignable_invocation_functionTypes_optional', () {
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_argumentTypeNotAssignable_invocation_functionTypes_optional);
@@ -14702,6 +15055,10 @@
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_assignmentToConst_localVariable);
       });
+      _ut.test('test_assignmentToFinal_excludedSetter', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_assignmentToFinal_excludedSetter);
+      });
       _ut.test('test_assignmentToFinal_instanceVariable', () {
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_assignmentToFinal_instanceVariable);
@@ -14750,6 +15107,10 @@
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_concreteClassWithAbstractMember);
       });
+      _ut.test('test_conflictingDartImport', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_conflictingDartImport);
+      });
       _ut.test('test_conflictingInstanceGetterAndSuperclassMember_direct_field', () {
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_conflictingInstanceGetterAndSuperclassMember_direct_field);
@@ -14854,6 +15215,18 @@
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_finalNotInitialized_local_final);
       });
+      _ut.test('test_functionWithoutCall_direct', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_functionWithoutCall_direct);
+      });
+      _ut.test('test_functionWithoutCall_indirect_extends', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_functionWithoutCall_indirect_extends);
+      });
+      _ut.test('test_functionWithoutCall_indirect_implements', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_functionWithoutCall_indirect_implements);
+      });
       _ut.test('test_importDuplicatedLibraryName', () {
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_importDuplicatedLibraryName);
@@ -14954,9 +15327,17 @@
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_invalidOverrideNamed_missingNamedParameter);
       });
-      _ut.test('test_invalidOverridePositional', () {
+      _ut.test('test_invalidOverridePositional_optional', () {
         final __test = new StaticWarningCodeTest();
-        runJUnitTest(__test, __test.test_invalidOverridePositional);
+        runJUnitTest(__test, __test.test_invalidOverridePositional_optional);
+      });
+      _ut.test('test_invalidOverridePositional_optionalAndRequired', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_invalidOverridePositional_optionalAndRequired);
+      });
+      _ut.test('test_invalidOverridePositional_optionalAndRequired2', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_invalidOverridePositional_optionalAndRequired2);
       });
       _ut.test('test_invalidOverrideRequired', () {
         final __test = new StaticWarningCodeTest();
@@ -15046,6 +15427,10 @@
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_nonAbstractClassInheritsAbstractMemberOne_method_optionalParamCount);
       });
+      _ut.test('test_nonAbstractClassInheritsAbstractMemberOne_setter_excluded', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_nonAbstractClassInheritsAbstractMemberOne_setter_excluded);
+      });
       _ut.test('test_nonAbstractClassInheritsAbstractMemberOne_setter_fromInterface', () {
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_nonAbstractClassInheritsAbstractMemberOne_setter_fromInterface);
@@ -15234,6 +15619,14 @@
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedIdentifier_methodInvocation);
       });
+      _ut.test('test_undefinedIdentifier_private_getter', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_undefinedIdentifier_private_getter);
+      });
+      _ut.test('test_undefinedIdentifier_private_setter', () {
+        final __test = new StaticWarningCodeTest();
+        runJUnitTest(__test, __test.test_undefinedIdentifier_private_setter);
+      });
       _ut.test('test_undefinedNamedParameter', () {
         final __test = new StaticWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedNamedParameter);
@@ -15661,6 +16054,7 @@
         provider.objectType.element,
         provider.stackTraceType.element,
         provider.stringType.element,
+        provider.symbolType.element,
         provider.typeType.element];
     coreUnit.functions = <FunctionElement> [ElementFactory.functionElement3("identical", provider.boolType.element, <ClassElement> [provider.objectType.element, provider.objectType.element], null)];
     LibraryElementImpl coreLibrary = new LibraryElementImpl(sdkContext, ASTFactory.libraryIdentifier2(["dart", "core"]));
@@ -15794,7 +16188,7 @@
     GatheringErrorListener errorListener = new GatheringErrorListener();
     Scope scope = new LibraryImportScope(importingLibrary, errorListener);
     JUnitTestCase.assertEquals(type, scope.lookup(ASTFactory.identifier3(typeName), importingLibrary));
-    errorListener.assertNoErrors();
+    errorListener.assertErrors2([StaticWarningCode.CONFLICTING_DART_IMPORT]);
   }
   void test_nonConflictingImports_sameElement() {
     AnalysisContext context = new AnalysisContextImpl();
@@ -17473,6 +17867,145 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_undefinedGetter_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  get b => 0;",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    return a.b;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedMethod_assignmentExpression_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  operator +(B b) {return new B();}",
+        "}",
+        "f(var a, var a2) {",
+        "  a = new A();",
+        "  a2 = new A();",
+        "  a += a2;",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedMethod_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  b() {}",
+        "}",
+        "f() {",
+        "  var a = new A();",
+        "  a.b();",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedOperator_binaryExpression_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  operator +(B b) {}",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a + 1;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedOperator_indexBoth_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  operator [](int index) {}",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a[0]++;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedOperator_indexGetter_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  operator [](int index) {}",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a[0];",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedOperator_indexSetter_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  operator []=(i, v) {}",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a[0] = 1;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedOperator_postfixExpression() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  operator +(B b) {return new B();}",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a++;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedOperator_prefixExpression() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  operator +(B b) {return new B();}",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    ++a;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
+  void test_undefinedSetter_inSubtype() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B extends A {",
+        "  set b(x) {}",
+        "}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a.b = 0;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+  }
   void test_unnecessaryCast_dynamic_type() {
     Source source = addSource(EngineTestCase.createSource(["m(v) {", "  var b = v as Object;", "}"]));
     resolve(source);
@@ -17618,6 +18151,46 @@
         final __test = new NonHintCodeTest();
         runJUnitTest(__test, __test.test_overrideEqualsButNotHashCode);
       });
+      _ut.test('test_undefinedGetter_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedGetter_inSubtype);
+      });
+      _ut.test('test_undefinedMethod_assignmentExpression_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedMethod_assignmentExpression_inSubtype);
+      });
+      _ut.test('test_undefinedMethod_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedMethod_inSubtype);
+      });
+      _ut.test('test_undefinedOperator_binaryExpression_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_binaryExpression_inSubtype);
+      });
+      _ut.test('test_undefinedOperator_indexBoth_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_indexBoth_inSubtype);
+      });
+      _ut.test('test_undefinedOperator_indexGetter_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_indexGetter_inSubtype);
+      });
+      _ut.test('test_undefinedOperator_indexSetter_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_indexSetter_inSubtype);
+      });
+      _ut.test('test_undefinedOperator_postfixExpression', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_postfixExpression);
+      });
+      _ut.test('test_undefinedOperator_prefixExpression', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_prefixExpression);
+      });
+      _ut.test('test_undefinedSetter_inSubtype', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedSetter_inSubtype);
+      });
       _ut.test('test_unnecessaryCast_13855_parameter_A', () {
         final __test = new NonHintCodeTest();
         runJUnitTest(__test, __test.test_unnecessaryCast_13855_parameter_A);
@@ -18765,12 +19338,96 @@
     });
   }
 }
+class SubtypeManagerTest extends EngineTestCase {
+
+  /**
+   * The inheritance manager being tested.
+   */
+  SubtypeManager _subtypeManager;
+
+  /**
+   * The compilation unit element containing all of the types setup in each test.
+   */
+  CompilationUnitElementImpl _definingCompilationUnit;
+  void test_computeAllSubtypes_infiniteLoop() {
+    ClassElementImpl classA = ElementFactory.classElement2("A", []);
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type, []);
+    classA.supertype = classB.type;
+    _definingCompilationUnit.types = <ClassElement> [classA, classB];
+    Set<ClassElement> subtypesOfA = _subtypeManager.computeAllSubtypes(classA);
+    List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA);
+    EngineTestCase.assertSize3(2, subtypesOfA);
+    EngineTestCase.assertContains(arraySubtypesOfA, [classA, classB]);
+  }
+  void test_computeAllSubtypes_manyRecursiveSubtypes() {
+    ClassElementImpl classA = ElementFactory.classElement2("A", []);
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type, []);
+    ClassElementImpl classC = ElementFactory.classElement("C", classB.type, []);
+    ClassElementImpl classD = ElementFactory.classElement("D", classB.type, []);
+    ClassElementImpl classE = ElementFactory.classElement("E", classB.type, []);
+    _definingCompilationUnit.types = <ClassElement> [classA, classB, classC, classD, classE];
+    Set<ClassElement> subtypesOfA = _subtypeManager.computeAllSubtypes(classA);
+    List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA);
+    Set<ClassElement> subtypesOfB = _subtypeManager.computeAllSubtypes(classB);
+    List<ClassElement> arraySubtypesOfB = new List.from(subtypesOfB);
+    EngineTestCase.assertSize3(4, subtypesOfA);
+    EngineTestCase.assertContains(arraySubtypesOfA, [classB, classC, classD, classE]);
+    EngineTestCase.assertSize3(3, subtypesOfB);
+    EngineTestCase.assertContains(arraySubtypesOfB, [classC, classD, classE]);
+  }
+  void test_computeAllSubtypes_noSubtypes() {
+    ClassElementImpl classA = ElementFactory.classElement2("A", []);
+    _definingCompilationUnit.types = <ClassElement> [classA];
+    Set<ClassElement> subtypesOfA = _subtypeManager.computeAllSubtypes(classA);
+    EngineTestCase.assertSize3(0, subtypesOfA);
+  }
+  void test_computeAllSubtypes_oneSubtype() {
+    ClassElementImpl classA = ElementFactory.classElement2("A", []);
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type, []);
+    _definingCompilationUnit.types = <ClassElement> [classA, classB];
+    Set<ClassElement> subtypesOfA = _subtypeManager.computeAllSubtypes(classA);
+    List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA);
+    EngineTestCase.assertSize3(1, subtypesOfA);
+    EngineTestCase.assertContains(arraySubtypesOfA, [classB]);
+  }
+  void setUp() {
+    super.setUp();
+    AnalysisContextImpl context = AnalysisContextFactory.contextWithCore();
+    FileBasedSource source = new FileBasedSource.con1(new ContentCache(), FileUtilities2.createFile("/test.dart"));
+    _definingCompilationUnit = new CompilationUnitElementImpl("test.dart");
+    _definingCompilationUnit.source = source;
+    LibraryElementImpl definingLibrary = ElementFactory.library(context, "test");
+    definingLibrary.definingCompilationUnit = _definingCompilationUnit;
+    _subtypeManager = new SubtypeManager();
+  }
+  static dartSuite() {
+    _ut.group('SubtypeManagerTest', () {
+      _ut.test('test_computeAllSubtypes_infiniteLoop', () {
+        final __test = new SubtypeManagerTest();
+        runJUnitTest(__test, __test.test_computeAllSubtypes_infiniteLoop);
+      });
+      _ut.test('test_computeAllSubtypes_manyRecursiveSubtypes', () {
+        final __test = new SubtypeManagerTest();
+        runJUnitTest(__test, __test.test_computeAllSubtypes_manyRecursiveSubtypes);
+      });
+      _ut.test('test_computeAllSubtypes_noSubtypes', () {
+        final __test = new SubtypeManagerTest();
+        runJUnitTest(__test, __test.test_computeAllSubtypes_noSubtypes);
+      });
+      _ut.test('test_computeAllSubtypes_oneSubtype', () {
+        final __test = new SubtypeManagerTest();
+        runJUnitTest(__test, __test.test_computeAllSubtypes_oneSubtype);
+      });
+    });
+  }
+}
 main() {
 //  ElementResolverTest.dartSuite();
 //  InheritanceManagerTest.dartSuite();
 //  LibraryElementBuilderTest.dartSuite();
 //  LibraryTest.dartSuite();
 //  StaticTypeAnalyzerTest.dartSuite();
+//  SubtypeManagerTest.dartSuite();
 //  TypeOverrideManagerTest.dartSuite();
 //  TypeProviderImplTest.dartSuite();
 //  TypeResolverVisitorTest.dartSuite();
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index 56605c2..6df4315 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -55,8 +55,12 @@
   final _onDirtyController = new StreamController.broadcast(sync: true);
 
   /// A stream that emits an event whenever this transform logs an entry.
+  ///
+  /// This is synchronous because error logs can cause the transform to fail, so
+  /// we need to ensure that their processing isn't delayed until after the
+  /// transform or build has finished.
   Stream<LogEntry> get onLog => _onLogController.stream;
-  final _onLogController = new StreamController<LogEntry>.broadcast();
+  final _onLogController = new StreamController<LogEntry>.broadcast(sync: true);
 
   TransformNode(this.phase, this.transformer, this.primary) {
     _primarySubscription = primary.onStateChange.listen((state) {
diff --git a/pkg/barback/test/utils.dart b/pkg/barback/test/utils.dart
index 4e970d8..6d88ee5 100644
--- a/pkg/barback/test/utils.dart
+++ b/pkg/barback/test/utils.dart
@@ -469,7 +469,9 @@
     _assets[id.package][id].contents = contents;
   }
 
-  void _setAssetError(String name) => _errors.add(new AssetId.parse(name));
+  void _setAssetError(String name) {
+    _errors.add(new AssetId.parse(name));
+  }
 
   List<AssetId> listAssets(String package, {String within}) {
     if (within != null) {
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js
index e140b76..71af132 100644
--- a/pkg/browser/lib/interop.js
+++ b/pkg/browser/lib/interop.js
@@ -468,52 +468,16 @@
   function construct(args) {
     args = args.map(deserialize);
     var constructor = args[0];
-    args = Array.prototype.slice.call(args, 1);
 
-    // Until 10 args, the 'new' operator is used. With more arguments we use a
-    // generic way that may not work, particularly when the constructor does not
-    // have an "apply" method.
-    var ret = null;
-    if (args.length === 0) {
-      ret = new constructor();
-    } else if (args.length === 1) {
-      ret = new constructor(args[0]);
-    } else if (args.length === 2) {
-      ret = new constructor(args[0], args[1]);
-    } else if (args.length === 3) {
-      ret = new constructor(args[0], args[1], args[2]);
-    } else if (args.length === 4) {
-      ret = new constructor(args[0], args[1], args[2], args[3]);
-    } else if (args.length === 5) {
-      ret = new constructor(args[0], args[1], args[2], args[3], args[4]);
-    } else if (args.length === 6) {
-      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
-                            args[5]);
-    } else if (args.length === 7) {
-      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
-                            args[5], args[6]);
-    } else if (args.length === 8) {
-      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
-                            args[5], args[6], args[7]);
-    } else if (args.length === 9) {
-      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
-                            args[5], args[6], args[7], args[8]);
-    } else if (args.length === 10) {
-      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
-                            args[5], args[6], args[7], args[8], args[9]);
-    } else {
-      // Dummy Type with correct constructor.
-      var Type = function(){};
-      Type.prototype = constructor.prototype;
-
-      // Create a new instance
-      var instance = new Type();
-
-      // Call the original constructor.
-      ret = constructor.apply(instance, args);
-      ret = Object(ret) === ret ? ret : instance;
-    }
-    return serialize(ret);
+    // The following code solves the problem of invoking a JavaScript
+    // constructor with an unknown number arguments.
+    // First bind the constructor to the argument list using bind.apply().
+    // The first argument to bind() is the binding of 'this', make it 'null'
+    // After that, use the JavaScript 'new' operator which overrides any binding
+    // of 'this' with the new instance.
+    args[0] = null;
+    var factoryFunction = constructor.bind.apply(constructor, args);
+    return serialize(new factoryFunction());
   }
 
   // Remote handler to return the top-level JavaScript context.
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index 13f83af..7ec72ec 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -198,7 +198,7 @@
  */
 Future<MirrorSystem> _analyzeLibraries(List<String> libraries,
       String libraryRoot, {String packageRoot}) {
-  SourceFileProvider provider = new SourceFileProvider();
+  SourceFileProvider provider = new CompilerSourceFileProvider();
   api.DiagnosticHandler diagnosticHandler =
         new FormattingDiagnosticHandler(provider).diagnosticHandler;
   Uri libraryUri = new Uri(scheme: 'file', path: appendSlash(libraryRoot));
diff --git a/pkg/intl/lib/extract_messages.dart b/pkg/intl/lib/extract_messages.dart
index 2a34a43..412c3a8 100644
--- a/pkg/intl/lib/extract_messages.dart
+++ b/pkg/intl/lib/extract_messages.dart
@@ -217,9 +217,9 @@
       Function setAttribute) {
     var message = new MainMessage();
     message.name = name;
-    message.arguments = parameters.parameters.elements.map(
+    message.arguments = parameters.parameters.map(
         (x) => x.identifier.name).toList();
-    var arguments = node.argumentList.arguments.elements;
+    var arguments = node.argumentList.arguments;
     extract(message, arguments);
 
     for (var namedArgument in arguments.where((x) => x is NamedExpression)) {
@@ -446,7 +446,7 @@
         warnings.add(err);
       }
     });
-    var mainArg = node.argumentList.arguments.elements.firstWhere(
+    var mainArg = node.argumentList.arguments.firstWhere(
         (each) => each is! NamedExpression);
     if (mainArg is SimpleStringLiteral) {
       message.mainArgument = mainArg.toString();
diff --git a/pkg/intl/lib/src/intl_message.dart b/pkg/intl/lib/src/intl_message.dart
index 2fe5fd0..7da13ee 100644
--- a/pkg/intl/lib/src/intl_message.dart
+++ b/pkg/intl/lib/src/intl_message.dart
@@ -459,7 +459,7 @@
    * argument names and values.
    */
   Map argumentsOfInterestFor(MethodInvocation node) {
-    var basicArguments = node.argumentList.arguments.elements;
+    var basicArguments = node.argumentList.arguments;
     var others = basicArguments.where((each) => each is NamedExpression);
     return new Map.fromIterable(others,
         key: (node) => node.name.label.token.value(),
@@ -643,7 +643,7 @@
    * arguments used in Plural/Gender.
    */
   Map argumentsOfInterestFor(MethodInvocation node) {
-    var casesArgument = node.argumentList.arguments.elements[1];
+    var casesArgument = node.argumentList.arguments[1];
     return new Map.fromIterable(casesArgument.entries,
       key: (node) => node.key.value,
       value: (node) => node.value);
diff --git a/pkg/mdv/lib/src/input_bindings.dart b/pkg/mdv/lib/src/input_bindings.dart
index cdd89b5..fa15841 100644
--- a/pkg/mdv/lib/src/input_bindings.dart
+++ b/pkg/mdv/lib/src/input_bindings.dart
@@ -123,7 +123,7 @@
   // TODO(jmesserly): polyfill document.contains API instead of doing it here
   static bool _isNodeInDocument(Node node) {
     // On non-IE this works:
-    // return node.document.contains(node);
+    // return node.ownerDocument.contains(node);
     var document = node.document;
     if (node == document || node.parentNode == document) return true;
     return document.documentElement.contains(node);
diff --git a/pkg/mdv/test/custom_element_bindings_test.dart b/pkg/mdv/test/custom_element_bindings_test.dart
index 3952fe1..3150a27 100644
--- a/pkg/mdv/test/custom_element_bindings_test.dart
+++ b/pkg/mdv/test/custom_element_bindings_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:html';
 import 'package:mdv/mdv.dart' as mdv;
+import 'package:observe/observe.dart' show toObservable;
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 import 'mdv_test_utils.dart';
@@ -43,7 +44,7 @@
 
   observeTest('override bind/unbind/unbindAll', () {
     var element = new MyCustomElement();
-    var model = toSymbolMap({'a': new Point(123, 444), 'b': new Monster(100)});
+    var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
 
     element.bind('my-point', model, 'a');
     element.bind('scary-monster', model, 'b');
@@ -51,29 +52,29 @@
     expect(element.attributes, isNot(contains('my-point')));
     expect(element.attributes, isNot(contains('scary-monster')));
 
-    expect(element.myPoint, model[#a]);
-    expect(element.scaryMonster, model[#b]);
+    expect(element.myPoint, model['a']);
+    expect(element.scaryMonster, model['b']);
 
-    model[#a] = null;
+    model['a'] = null;
     performMicrotaskCheckpoint();
     expect(element.myPoint, null);
     element.unbind('my-point');
 
-    model[#a] = new Point(1, 2);
-    model[#b] = new Monster(200);
+    model['a'] = new Point(1, 2);
+    model['b'] = new Monster(200);
     performMicrotaskCheckpoint();
-    expect(element.scaryMonster, model[#b]);
+    expect(element.scaryMonster, model['b']);
     expect(element.myPoint, null, reason: 'a was unbound');
 
     element.unbindAll();
-    model[#b] = null;
+    model['b'] = null;
     performMicrotaskCheckpoint();
     expect(element.scaryMonster.health, 200);
   });
 
   observeTest('override attribute setter', () {
     var element = new WithAttrsCustomElement().real;
-    var model = toSymbolMap({'a': 1, 'b': 2});
+    var model = toObservable({'a': 1, 'b': 2});
     element.bind('hidden?', model, 'a');
     element.bind('id', model, 'b');
 
@@ -81,22 +82,22 @@
     expect(element.attributes['hidden'], '');
     expect(element.id, '2');
 
-    model[#a] = null;
+    model['a'] = null;
     performMicrotaskCheckpoint();
     expect(element.attributes, isNot(contains('hidden')),
         reason: 'null is false-y');
 
-    model[#a] = false;
+    model['a'] = false;
     performMicrotaskCheckpoint();
     expect(element.attributes, isNot(contains('hidden')));
 
-    model[#a] = 'foo';
+    model['a'] = 'foo';
     // TODO(jmesserly): this is here to force an ordering between the two
     // changes. Otherwise the order depends on what order StreamController
     // chooses to fire the two listeners in.
     performMicrotaskCheckpoint();
 
-    model[#b] = 'x';
+    model['b'] = 'x';
     performMicrotaskCheckpoint();
     expect(element.attributes, contains('hidden'));
     expect(element.attributes['hidden'], '');
@@ -115,7 +116,7 @@
 
   observeTest('template bind uses overridden custom element bind', () {
 
-    var model = toSymbolMap({'a': new Point(123, 444), 'b': new Monster(100)});
+    var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
 
     var div = createTestHtml('<template bind>'
           '<my-custom-element my-point="{{a}}" scary-monster="{{b}}">'
@@ -137,13 +138,13 @@
     expect(element.xtag is MyCustomElement, true,
         reason: '${element.xtag} should be a MyCustomElement');
 
-    expect(element.xtag.myPoint, model[#a]);
-    expect(element.xtag.scaryMonster, model[#b]);
+    expect(element.xtag.myPoint, model['a']);
+    expect(element.xtag.scaryMonster, model['b']);
 
     expect(element.attributes, isNot(contains('my-point')));
     expect(element.attributes, isNot(contains('scary-monster')));
 
-    model[#a] = null;
+    model['a'] = null;
     performMicrotaskCheckpoint();
     expect(element.xtag.myPoint, null);
 
@@ -152,8 +153,8 @@
 
     expect(element.parentNode, null, reason: 'element was detached');
 
-    model[#a] = new Point(1, 2);
-    model[#b] = new Monster(200);
+    model['a'] = new Point(1, 2);
+    model['b'] = new Monster(200);
     performMicrotaskCheckpoint();
 
     expect(element.xtag.myPoint, null, reason: 'model was unbound');
diff --git a/pkg/mdv/test/element_bindings_test.dart b/pkg/mdv/test/element_bindings_test.dart
index 0cf9b04..8ffbc5c 100644
--- a/pkg/mdv/test/element_bindings_test.dart
+++ b/pkg/mdv/test/element_bindings_test.dart
@@ -38,49 +38,49 @@
   observeTest('Text', () {
     var template = new Element.html('<template bind>{{a}} and {{b}}');
     testDiv.append(template);
-    var model = toSymbolMap({'a': 1, 'b': 2});
+    var model = toObservable({'a': 1, 'b': 2});
     template.model = model;
     performMicrotaskCheckpoint();
     var text = testDiv.nodes[1];
     expect(text.text, '1 and 2');
 
-    model[#a] = 3;
+    model['a'] = 3;
     performMicrotaskCheckpoint();
     expect(text.text, '3 and 2');
   });
 
   observeTest('SimpleBinding', () {
     var el = new DivElement();
-    var model = toSymbolMap({'a': '1'});
+    var model = toObservable({'a': '1'});
     el.bind('foo', model, 'a');
     performMicrotaskCheckpoint();
     expect(el.attributes['foo'], '1');
 
-    model[#a] = '2';
+    model['a'] = '2';
     performMicrotaskCheckpoint();
     expect(el.attributes['foo'], '2');
 
-    model[#a] = 232.2;
+    model['a'] = 232.2;
     performMicrotaskCheckpoint();
     expect(el.attributes['foo'], '232.2');
 
-    model[#a] = 232;
+    model['a'] = 232;
     performMicrotaskCheckpoint();
     expect(el.attributes['foo'], '232');
 
-    model[#a] = null;
+    model['a'] = null;
     performMicrotaskCheckpoint();
     expect(el.attributes['foo'], '');
   });
 
   observeTest('SimpleBindingWithDashes', () {
     var el = new DivElement();
-    var model = toSymbolMap({'a': '1'});
+    var model = toObservable({'a': '1'});
     el.bind('foo-bar', model, 'a');
     performMicrotaskCheckpoint();
     expect(el.attributes['foo-bar'], '1');
 
-    model[#a] = '2';
+    model['a'] = '2';
     performMicrotaskCheckpoint();
     expect(el.attributes['foo-bar'], '2');
   });
@@ -88,18 +88,18 @@
   observeTest('SimpleBindingWithComment', () {
     var el = new DivElement();
     el.innerHtml = '<!-- Comment -->';
-    var model = toSymbolMap({'a': '1'});
+    var model = toObservable({'a': '1'});
     el.bind('foo-bar', model, 'a');
     performMicrotaskCheckpoint();
     expect(el.attributes['foo-bar'], '1');
 
-    model[#a] = '2';
+    model['a'] = '2';
     performMicrotaskCheckpoint();
     expect(el.attributes['foo-bar'], '2');
   });
 
   observeTest('PlaceHolderBindingText', () {
-    var model = toSymbolMap({
+    var model = toObservable({
       'adj': 'cruel',
       'noun': 'world'
     });
@@ -116,13 +116,13 @@
     el = testDiv.nodes[1].nodes.first;
     expect(el.text, 'Hello cruel world!');
 
-    model[#adj] = 'happy';
+    model['adj'] = 'happy';
     performMicrotaskCheckpoint();
     expect(el.text, 'Hello happy world!');
   });
 
   observeTest('InputElementTextBinding', () {
-    var model = toSymbolMap({'val': 'ping'});
+    var model = toObservable({'val': 'ping'});
 
     var el = new InputElement();
     el.bind('value', model, 'val');
@@ -131,10 +131,10 @@
 
     el.value = 'pong';
     dispatchEvent('input', el);
-    expect(model[#val], 'pong');
+    expect(model['val'], 'pong');
 
     // Try a deep path.
-    model = toSymbolMap({'a': {'b': {'c': 'ping'}}});
+    model = toObservable({'a': {'b': {'c': 'ping'}}});
 
     el.bind('value', model, 'a.b.c');
     performMicrotaskCheckpoint();
@@ -145,7 +145,7 @@
     expect(observePath(model, 'a.b.c').value, 'pong');
 
     // Start with the model property being absent.
-    model[#a][#b].remove(#c);
+    model['a']['b'].remove('c');
     performMicrotaskCheckpoint();
     expect(el.value, '');
 
@@ -155,7 +155,7 @@
     performMicrotaskCheckpoint();
 
     // Model property unreachable (and unsettable).
-    model[#a].remove(#b);
+    model['a'].remove('b');
     performMicrotaskCheckpoint();
     expect(el.value, '');
 
@@ -165,7 +165,7 @@
   });
 
   observeTest('InputElementCheckbox', () {
-    var model = toSymbolMap({'val': true});
+    var model = toObservable({'val': true});
 
     var el = new InputElement();
     testDiv.append(el);
@@ -174,28 +174,28 @@
     performMicrotaskCheckpoint();
     expect(el.checked, true);
 
-    model[#val] = false;
+    model['val'] = false;
     performMicrotaskCheckpoint();
     expect(el.checked, false);
 
     el.click();
-    expect(model[#val], true);
+    expect(model['val'], true);
 
     el.click();
-    expect(model[#val], false);
+    expect(model['val'], false);
 
     el.onClick.listen((_) {
-      expect(model[#val], true);
+      expect(model['val'], true);
     });
     el.onChange.listen((_) {
-      expect(model[#val], true);
+      expect(model['val'], true);
     });
 
     el.dispatchEvent(new MouseEvent('click', view: window));
   });
 
   observeTest('InputElementCheckbox - binding updated on click', () {
-    var model = toSymbolMap({'val': true});
+    var model = toObservable({'val': true});
 
     var el = new InputElement();
     testDiv.append(el);
@@ -205,14 +205,14 @@
     expect(el.checked, true);
 
     el.onClick.listen((_) {
-      expect(model[#val], false);
+      expect(model['val'], false);
     });
 
     el.dispatchEvent(new MouseEvent('click', view: window));
   });
 
   observeTest('InputElementCheckbox - binding updated on change', () {
-    var model = toSymbolMap({'val': true});
+    var model = toObservable({'val': true});
 
     var el = new InputElement();
     testDiv.append(el);
@@ -222,14 +222,14 @@
     expect(el.checked, true);
 
     el.onChange.listen((_) {
-      expect(model[#val], false);
+      expect(model['val'], false);
     });
 
     el.dispatchEvent(new MouseEvent('click', view: window));
    });
 
   observeTest('InputElementRadio', () {
-    var model = toSymbolMap({'val1': true, 'val2': false, 'val3': false,
+    var model = toObservable({'val1': true, 'val2': false, 'val3': false,
         'val4': true});
     var RADIO_GROUP_NAME = 'observeTest';
 
@@ -265,8 +265,8 @@
     expect(el3.checked, false);
     expect(el4.checked, true);
 
-    model[#val1] = false;
-    model[#val2] = true;
+    model['val1'] = false;
+    model['val2'] = true;
     performMicrotaskCheckpoint();
     expect(el1.checked, false);
     expect(el2.checked, true);
@@ -275,21 +275,21 @@
 
     el1.checked = true;
     dispatchEvent('change', el1);
-    expect(model[#val1], true);
-    expect(model[#val2], false);
-    expect(model[#val3], false);
-    expect(model[#val4], true);
+    expect(model['val1'], true);
+    expect(model['val2'], false);
+    expect(model['val3'], false);
+    expect(model['val4'], true);
 
     el3.checked = true;
     dispatchEvent('change', el3);
-    expect(model[#val1], false);
-    expect(model[#val2], false);
-    expect(model[#val3], true);
-    expect(model[#val4], true);
+    expect(model['val1'], false);
+    expect(model['val2'], false);
+    expect(model['val3'], true);
+    expect(model['val4'], true);
   });
 
   observeTest('InputElementRadioMultipleForms', () {
-    var model = toSymbolMap({'val1': true, 'val2': false, 'val3': false,
+    var model = toObservable({'val1': true, 'val2': false, 'val3': false,
         'val4': true});
     var RADIO_GROUP_NAME = 'observeTest';
 
@@ -330,21 +330,21 @@
 
     el2.checked = true;
     dispatchEvent('change', el2);
-    expect(model[#val1], false);
-    expect(model[#val2], true);
+    expect(model['val1'], false);
+    expect(model['val2'], true);
 
     // Radio buttons in form2 should be unaffected
-    expect(model[#val3], false);
-    expect(model[#val4], true);
+    expect(model['val3'], false);
+    expect(model['val4'], true);
 
     el3.checked = true;
     dispatchEvent('change', el3);
-    expect(model[#val3], true);
-    expect(model[#val4], false);
+    expect(model['val3'], true);
+    expect(model['val4'], false);
 
     // Radio buttons in form1 should be unaffected
-    expect(model[#val1], false);
-    expect(model[#val2], true);
+    expect(model['val1'], false);
+    expect(model['val2'], true);
   });
 
   observeTest('BindToChecked', () {
@@ -356,14 +356,14 @@
     child.append(input);
     input.type = 'checkbox';
 
-    var model = toSymbolMap({'a': {'b': false}});
+    var model = toObservable({'a': {'b': false}});
     input.bind('checked', model, 'a.b');
 
     input.click();
-    expect(model[#a][#b], true);
+    expect(model['a']['b'], true);
 
     input.click();
-    expect(model[#a][#b], false);
+    expect(model['a']['b'], false);
   });
 
   observeTest('Select selectedIndex', () {
@@ -373,7 +373,7 @@
     var option1 = select.append(new OptionElement());
     var option2 = select.append(new OptionElement());
 
-    var model = toSymbolMap({'val': 2});
+    var model = toObservable({'val': 2});
 
     select.bind('selectedIndex', model, 'val');
     performMicrotaskCheckpoint();
@@ -381,7 +381,7 @@
 
     select.selectedIndex = 1;
     dispatchEvent('change', select);
-    expect(model[#val], 1);
+    expect(model['val'], 1);
   });
 
   observeTest('MultipleReferences', () {
@@ -390,7 +390,7 @@
     template.content.append(el);
     testDiv.append(template);
 
-    var model = toSymbolMap({'foo': 'bar'});
+    var model = toObservable({'foo': 'bar'});
     el.attributes['foo'] = '{{foo}} {{foo}}';
     template.model = model;
 
diff --git a/pkg/mdv/test/mdv_test_utils.dart b/pkg/mdv/test/mdv_test_utils.dart
index 97893de..7f76506 100644
--- a/pkg/mdv/test/mdv_test_utils.dart
+++ b/pkg/mdv/test/mdv_test_utils.dart
@@ -17,15 +17,6 @@
       div.firstChild.firstChild.tagName == 'TEMPLATE';
 }();
 
-toSymbolMap(Map map) {
-  var result = new ObservableMap.linked();
-  map.forEach((key, value) {
-    if (value is Map) value = toSymbolMap(value);
-    result[new Symbol(key)] = value;
-  });
-  return result;
-}
-
 recursivelySetTemplateModel(element, model, [delegate]) {
   for (var node in element.queryAll('*')) {
     if (node.isTemplate) {
@@ -39,7 +30,7 @@
   target.dispatchEvent(new Event(type, cancelable: false));
 }
 
-class FooBarModel extends ObservableBase {
+class FooBarModel extends Observable {
   @observable var foo;
   @observable var bar;
 
@@ -47,7 +38,7 @@
 }
 
 @reflectable
-class FooBarNotifyModel extends ChangeNotifierBase implements FooBarModel {
+class FooBarNotifyModel extends ChangeNotifier implements FooBarModel {
   var _foo;
   var _bar;
 
diff --git a/pkg/mdv/test/node_bindings_test.dart b/pkg/mdv/test/node_bindings_test.dart
index c13e588..a12e878 100644
--- a/pkg/mdv/test/node_bindings_test.dart
+++ b/pkg/mdv/test/node_bindings_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:html';
 import 'package:mdv/mdv.dart' as mdv;
+import 'package:observe/observe.dart' show toObservable;
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 import 'mdv_test_utils.dart';
@@ -33,16 +34,16 @@
 
   observeTest('Text', () {
     var text = new Text('hi');
-    var model = toSymbolMap({'a': 1});
+    var model = toObservable({'a': 1});
     text.bind('text', model, 'a');
     expect(text.text, '1');
 
-    model[#a] = 2;
+    model['a'] = 2;
     performMicrotaskCheckpoint();
     expect(text.text, '2');
 
     text.unbind('text');
-    model[#a] = 3;
+    model['a'] = 3;
     performMicrotaskCheckpoint();
     expect(text.text, '2');
 
@@ -51,7 +52,7 @@
 
   observeTest('Element', () {
     var element = new DivElement();
-    var model = toSymbolMap({'a': 1, 'b': 2});
+    var model = toObservable({'a': 1, 'b': 2});
     element.bind('hidden?', model, 'a');
     element.bind('id', model, 'b');
 
@@ -59,17 +60,17 @@
     expect(element.attributes['hidden'], '');
     expect(element.id, '2');
 
-    model[#a] = null;
+    model['a'] = null;
     performMicrotaskCheckpoint();
     expect(element.attributes, isNot(contains('hidden')),
         reason: 'null is false-y');
 
-    model[#a] = false;
+    model['a'] = false;
     performMicrotaskCheckpoint();
     expect(element.attributes, isNot(contains('hidden')));
 
-    model[#a] = 'foo';
-    model[#b] = 'x';
+    model['a'] = 'foo';
+    model['b'] = 'x';
     performMicrotaskCheckpoint();
     expect(element.attributes, contains('hidden'));
     expect(element.attributes['hidden'], '');
@@ -79,27 +80,27 @@
   inputTextAreaValueTest(String tagName) {
     var el = new Element.tag(tagName);
     testDiv.nodes.add(el);
-    var model = toSymbolMap({'x': 42});
+    var model = toObservable({'x': 42});
     el.bind('value', model, 'x');
     expect(el.value, '42');
 
-    model[#x] = 'Hi';
+    model['x'] = 'Hi';
     expect(el.value, '42', reason: 'changes delivered async');
     performMicrotaskCheckpoint();
     expect(el.value, 'Hi');
 
     el.value = 'changed';
     dispatchEvent('input', el);
-    expect(model[#x], 'changed');
+    expect(model['x'], 'changed');
 
     el.unbind('value');
 
     el.value = 'changed again';
     dispatchEvent('input', el);
-    expect(model[#x], 'changed');
+    expect(model['x'], 'changed');
 
     el.bind('value', model, 'x');
-    model[#x] = null;
+    model['x'] = null;
     performMicrotaskCheckpoint();
     expect(el.value, '');
   }
@@ -110,24 +111,24 @@
   observeTest('Radio Input', () {
     var input = new InputElement();
     input.type = 'radio';
-    var model = toSymbolMap({'x': true});
+    var model = toObservable({'x': true});
     input.bind('checked', model, 'x');
     expect(input.checked, true);
 
-    model[#x] = false;
+    model['x'] = false;
     expect(input.checked, true);
     performMicrotaskCheckpoint();
     expect(input.checked, false,reason: 'model change should update checked');
 
     input.checked = true;
     dispatchEvent('change', input);
-    expect(model[#x], true, reason: 'input.checked should set model');
+    expect(model['x'], true, reason: 'input.checked should set model');
 
     input.unbind('checked');
 
     input.checked = false;
     dispatchEvent('change', input);
-    expect(model[#x], true,
+    expect(model['x'], true,
         reason: 'disconnected binding should not fire');
   });
 
@@ -135,20 +136,20 @@
     var input = new InputElement();
     testDiv.append(input);
     input.type = 'checkbox';
-    var model = toSymbolMap({'x': true});
+    var model = toObservable({'x': true});
     input.bind('checked', model, 'x');
     expect(input.checked, true);
 
-    model[#x] = false;
+    model['x'] = false;
     expect(input.checked, true, reason: 'changes delivered async');
     performMicrotaskCheckpoint();
     expect(input.checked, false);
 
     input.click();
-    expect(model[#x], true);
+    expect(model['x'], true);
     performMicrotaskCheckpoint();
 
     input.click();
-    expect(model[#x], false);
+    expect(model['x'], false);
   });
 }
diff --git a/pkg/mdv/test/template_element_test.dart b/pkg/mdv/test/template_element_test.dart
index eeb2998..a39ad62 100644
--- a/pkg/mdv/test/template_element_test.dart
+++ b/pkg/mdv/test/template_element_test.dart
@@ -92,7 +92,7 @@
     var template = div.nodes[0];
     template.remove();
 
-    recursivelySetTemplateModel(template, toSymbolMap({}));
+    recursivelySetTemplateModel(template, toObservable({}));
     performMicrotaskCheckpoint();
     expect(template.nodes.length, 0);
     expect(template.nextNode, null);
@@ -103,7 +103,7 @@
     var template = div.nodes[0];
     var doc = document.implementation.createHtmlDocument('');
     doc.adoptNode(div);
-    recursivelySetTemplateModel(template, toSymbolMap({}));
+    recursivelySetTemplateModel(template, toObservable({}));
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
   });
@@ -120,12 +120,12 @@
     var div = createTestHtml('<template bind if="{{ foo }}">text</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
-    var m = toSymbolMap({ 'foo': null });
+    var m = toObservable({ 'foo': null });
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
 
-    m[#foo] = 1;
+    m['foo'] = 1;
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
     expect(div.lastChild.text, 'text');
@@ -134,12 +134,12 @@
   observeTest('Template Bind If, 2', () {
     var div = createTestHtml(
         '<template bind="{{ foo }}" if="{{ bar }}">{{ bat }}</template>');
-    var m = toSymbolMap({ 'bar': null, 'foo': { 'bat': 'baz' } });
+    var m = toObservable({ 'bar': null, 'foo': { 'bat': 'baz' } });
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
 
-    m[#bar] = 1;
+    m['bar'] = 1;
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
     expect(div.lastChild.text, 'baz');
@@ -149,12 +149,12 @@
     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
-    var m = toSymbolMap({ 'foo': null, 'value': 'foo' });
+    var m = toObservable({ 'foo': null, 'value': 'foo' });
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
 
-    m[#foo] = 1;
+    m['foo'] = 1;
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
     expect(div.lastChild.text, 'foo');
@@ -165,12 +165,12 @@
         '<template repeat="{{ foo }}" if="{{ bar }}">{{ }}</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
-    var m = toSymbolMap({ 'bar': null, 'foo': [1, 2, 3] });
+    var m = toObservable({ 'bar': null, 'foo': [1, 2, 3] });
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
 
-    m[#bar] = 1;
+    m['bar'] = 1;
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 4);
     expect(div.nodes[1].text, '1');
@@ -180,18 +180,18 @@
 
   observeTest('TextTemplateWithNullStringBinding', () {
     var div = createTestHtml('<template bind={{}}>a{{b}}c</template>');
-    var model = toSymbolMap({'b': 'B'});
+    var model = toObservable({'b': 'B'});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
     expect(div.nodes.length, 2);
     expect(div.nodes.last.text, 'aBc');
 
-    model[#b] = 'b';
+    model['b'] = 'b';
     deliverChanges(model);
     expect(div.nodes.last.text, 'abc');
 
-    model[#b] = null;
+    model['b'] = null;
     deliverChanges(model);
     expect(div.nodes.last.text, 'ac');
 
@@ -204,22 +204,22 @@
   observeTest('TextTemplateWithBindingPath', () {
     var div = createTestHtml(
         '<template bind="{{ data }}">a{{b}}c</template>');
-    var model = toSymbolMap({ 'data': {'b': 'B'} });
+    var model = toObservable({ 'data': {'b': 'B'} });
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
     expect(div.nodes.length, 2);
     expect(div.nodes.last.text, 'aBc');
 
-    model[#data][#b] = 'b';
+    model['data']['b'] = 'b';
     deliverChanges(model);
     expect(div.nodes.last.text, 'abc');
 
-    model[#data] = toSymbols({'b': 'X'});
+    model['data'] = toObservable({'b': 'X'});
     deliverChanges(model);
     expect(div.nodes.last.text, 'aXc');
 
-    model[#data] = null;
+    model['data'] = null;
     deliverChanges(model);
     expect(div.nodes.last.text, 'ac');
   });
@@ -227,26 +227,26 @@
   observeTest('TextTemplateWithBindingAndConditional', () {
     var div = createTestHtml(
         '<template bind="{{}}" if="{{ d }}">a{{b}}c</template>');
-    var model = toSymbolMap({'b': 'B', 'd': 1});
+    var model = toObservable({'b': 'B', 'd': 1});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
     expect(div.nodes.length, 2);
     expect(div.nodes.last.text, 'aBc');
 
-    model[#b] = 'b';
+    model['b'] = 'b';
     deliverChanges(model);
     expect(div.nodes.last.text, 'abc');
 
     // TODO(jmesserly): MDV set this to empty string and relies on JS conversion
     // rules. Is that intended?
     // See https://github.com/toolkitchen/mdv/issues/59
-    model[#d] = null;
+    model['d'] = null;
     deliverChanges(model);
     expect(div.nodes.length, 1);
 
-    model[#d] = 'here';
-    model[#b] = 'd';
+    model['d'] = 'here';
+    model['b'] = 'd';
 
     deliverChanges(model);
     expect(div.nodes.length, 2);
@@ -257,14 +257,14 @@
     var div = createTestHtml(
         '<template bind="{{ b }}">a{{value}}c</template>');
     expect(div.nodes.length, 1);
-    var model = toSymbolMap({'b': {'value': 'B'}});
+    var model = toObservable({'b': {'value': 'B'}});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
     expect(div.nodes.length, 2);
     expect(div.nodes.last.text, 'aBc');
 
-    model[#b] = toSymbols({'value': 'b'});
+    model['b'] = toObservable({'value': 'b'});
     deliverChanges(model);
     expect(div.nodes.last.text, 'abc');
   });
@@ -274,18 +274,18 @@
         '<template bind="{{}}">'
         '<div foo="a{{b}}c"></div>'
         '</template>');
-    var model = toSymbolMap({'b': 'B'});
+    var model = toObservable({'b': 'B'});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
     expect(div.nodes.length, 2);
     expect(div.nodes.last.attributes['foo'], 'aBc');
 
-    model[#b] = 'b';
+    model['b'] = 'b';
     deliverChanges(model);
     expect(div.nodes.last.attributes['foo'], 'abc');
 
-    model[#b] = 'X';
+    model['b'] = 'X';
     deliverChanges(model);
     expect(div.nodes.last.attributes['foo'], 'aXc');
   });
@@ -295,7 +295,7 @@
         '<template bind="{{}}">'
         '<div foo?="{{b}}"></div>'
         '</template>');
-    var model = toSymbolMap({'b': 'b'});
+    var model = toObservable({'b': 'b'});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
@@ -303,7 +303,7 @@
     expect(div.nodes.last.attributes['foo'], '');
     expect(div.nodes.last.attributes, isNot(contains('foo?')));
 
-    model[#b] = null;
+    model['b'] = null;
     deliverChanges(model);
     expect(div.nodes.last.attributes, isNot(contains('foo')));
   });
@@ -312,7 +312,7 @@
     var div = createTestHtml(
         '<template repeat="{{}}"">text</template>');
 
-    var model = toSymbols([0, 1, 2]);
+    var model = toObservable([0, 1, 2]);
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
@@ -322,7 +322,7 @@
     deliverChanges(model);
     expect(div.nodes.length, 2);
 
-    model.addAll(toSymbols([3, 4]));
+    model.addAll(toObservable([3, 4]));
     deliverChanges(model);
     expect(div.nodes.length, 4);
 
@@ -334,7 +334,7 @@
   observeTest('Repeat - Reuse Instances', () {
     var div = createTestHtml('<template repeat>{{ val }}</template>');
 
-    var model = toSymbols([
+    var model = toObservable([
       {'val': 10},
       {'val': 5},
       {'val': 2},
@@ -350,7 +350,7 @@
     addExpandos(template.nextNode);
     checkExpandos(template.nextNode);
 
-    model.sort((a, b) => a[#val] - b[#val]);
+    model.sort((a, b) => a['val'] - b['val']);
     deliverChanges(model);
     checkExpandos(template.nextNode);
 
@@ -360,7 +360,7 @@
     checkExpandos(template.nextNode);
 
     for (var item in model) {
-      item[#val] += 1;
+      item['val'] += 1;
     }
 
     deliverChanges(model);
@@ -395,7 +395,7 @@
     var div = createTestHtml(
         '<template repeat>text</template>');
 
-    var model = toSymbols([0, 1, 2]);
+    var model = toObservable([0, 1, 2]);
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
@@ -405,7 +405,7 @@
     deliverChanges(model);
     expect(div.nodes.length, 2);
 
-    model.addAll(toSymbols([3, 4]));
+    model.addAll(toObservable([3, 4]));
     deliverChanges(model);
     expect(div.nodes.length, 4);
 
@@ -417,7 +417,7 @@
   observeTest('Removal from iteration needs to unbind', () {
     var div = createTestHtml(
         '<template repeat="{{}}"><a>{{v}}</a></template>');
-    var model = toSymbols([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, {'v': 4}]);
+    var model = toObservable([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, {'v': 4}]);
     recursivelySetTemplateModel(div, model);
     deliverChanges(model);
 
@@ -434,8 +434,8 @@
       expect(nodes[i].text, '$i');
     }
 
-    vs[3][#v] = 33;
-    vs[4][#v] = 44;
+    vs[3]['v'] = 33;
+    vs[4]['v'] = 44;
     deliverChanges(model);
     for (var i = 0; i < 5; i++) {
       expect(nodes[i].text, '$i');
@@ -445,7 +445,7 @@
   observeTest('DOM Stability on Iteration', () {
     var div = createTestHtml(
         '<template repeat="{{}}">{{}}</template>');
-    var model = toSymbols([1, 2, 3, 4, 5]);
+    var model = toObservable([1, 2, 3, 4, 5]);
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
@@ -496,7 +496,7 @@
         '<template repeat="{{}}">{{value}}</template>');
     expect(div.nodes.length, 1);
 
-    var model = toSymbols([
+    var model = toObservable([
       {'value': 0},
       {'value': 1},
       {'value': 2}
@@ -509,14 +509,14 @@
     expect(div.nodes[2].text, '1');
     expect(div.nodes[3].text, '2');
 
-    model[1][#value] = 'One';
+    model[1]['value'] = 'One';
     deliverChanges(model);
     expect(div.nodes.length, 4);
     expect(div.nodes[1].text, '0');
     expect(div.nodes[2].text, 'One');
     expect(div.nodes[3].text, '2');
 
-    model.replaceRange(0, 1, toSymbols([{'value': 'Zero'}]));
+    model.replaceRange(0, 1, toObservable([{'value': 'Zero'}]));
     deliverChanges(model);
     expect(div.nodes.length, 4);
     expect(div.nodes[1].text, 'Zero');
@@ -529,21 +529,21 @@
         '<template bind="{{}}">'
         '<input value="{{x}}">'
         '</template>');
-    var model = toSymbolMap({'x': 'hi'});
+    var model = toObservable({'x': 'hi'});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
     expect(div.nodes.length, 2);
     expect(div.nodes.last.value, 'hi');
 
-    model[#x] = 'bye';
+    model['x'] = 'bye';
     expect(div.nodes.last.value, 'hi');
     deliverChanges(model);
     expect(div.nodes.last.value, 'bye');
 
     div.nodes.last.value = 'hello';
     dispatchEvent('input', div.nodes.last);
-    expect(model[#x], 'hello');
+    expect(model['x'], 'hello');
     deliverChanges(model);
     expect(div.nodes.last.value, 'hello');
   });
@@ -557,7 +557,7 @@
         '</template>'
         '<template bind="{{ XY }}" id="t2" ref="t1"></template>');
 
-    var model = toSymbolMap({
+    var model = toObservable({
       'XX': {'name': 'Leela', 'title': 'Captain'},
       'XY': {'name': 'Fry', 'title': 'Delivery boy'},
       'XZ': {'name': 'Zoidberg', 'title': 'Doctor'}
@@ -594,7 +594,7 @@
 
   observeTest('Bind', () {
     var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>');
-    var model = toSymbolMap({'name': 'Leela'});
+    var model = toObservable({'name': 'Leela'});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
@@ -608,7 +608,7 @@
         '</template>');
     var t = div.nodes.first;
 
-    var model = toSymbolMap({'name': 'Leela'});
+    var model = toObservable({'name': 'Leela'});
     t.bind('bind', model, '');
 
     deliverChanges(model);
@@ -617,7 +617,7 @@
 
   observeTest('BindPlaceHolderHasNewLine', () {
     var div = createTestHtml('<template bind="{{}}">Hi {{\nname\n}}</template>');
-    var model = toSymbolMap({'name': 'Leela'});
+    var model = toObservable({'name': 'Leela'});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
@@ -637,7 +637,7 @@
 
     expect(t2.ref, t1);
 
-    var model = toSymbolMap({'name': 'Fry'});
+    var model = toObservable({'name': 'Fry'});
     recursivelySetTemplateModel(div, model);
 
     deliverChanges(model);
@@ -645,7 +645,7 @@
   });
 
   observeTest('BindChanged', () {
-    var model = toSymbolMap({
+    var model = toObservable({
       'XX': {'name': 'Leela', 'title': 'Captain'},
       'XY': {'name': 'Fry', 'title': 'Delivery boy'},
       'XZ': {'name': 'Zoidberg', 'title': 'Doctor'}
@@ -684,7 +684,7 @@
         '<template repeat="{{ contacts }}">Hi {{ name }}</template>');
     var t = div.nodes.first;
 
-    var m = toSymbols({
+    var m = toObservable({
       'contacts': [
         {'name': 'Raf'},
         {'name': 'Arv'},
@@ -697,34 +697,34 @@
 
     assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']);
 
-    m[#contacts].add(toSymbols({'name': 'Alex'}));
+    m['contacts'].add(toObservable({'name': 'Alex'}));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']);
 
-    m[#contacts].replaceRange(0, 2,
-        toSymbols([{'name': 'Rafael'}, {'name': 'Erik'}]));
+    m['contacts'].replaceRange(0, 2,
+        toObservable([{'name': 'Rafael'}, {'name': 'Erik'}]));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']);
 
-    m[#contacts].removeRange(1, 3);
+    m['contacts'].removeRange(1, 3);
     deliverChanges(m);
     assertNodesAre(div, ['Hi Rafael', 'Hi Alex']);
 
-    m[#contacts].insertAll(1,
-        toSymbols([{'name': 'Erik'}, {'name': 'Dimitri'}]));
+    m['contacts'].insertAll(1,
+        toObservable([{'name': 'Erik'}, {'name': 'Dimitri'}]));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
 
-    m[#contacts].replaceRange(0, 1,
-        toSymbols([{'name': 'Tab'}, {'name': 'Neal'}]));
+    m['contacts'].replaceRange(0, 1,
+        toObservable([{'name': 'Tab'}, {'name': 'Neal'}]));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
 
-    m[#contacts] = toSymbols([{'name': 'Alex'}]);
+    m['contacts'] = toObservable([{'name': 'Alex'}]);
     deliverChanges(m);
     assertNodesAre(div, ['Hi Alex']);
 
-    m[#contacts].length = 0;
+    m['contacts'].length = 0;
     deliverChanges(m);
     assertNodesAre(div, []);
   });
@@ -734,7 +734,7 @@
         '<template repeat="{{ contacts }}">'
           'Hi {{ name }}'
         '</template>');
-    var m = toSymbols({
+    var m = toObservable({
       'contacts': [
         {'name': 'Raf'},
         {'name': 'Arv'},
@@ -753,7 +753,7 @@
     var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>');
     var t = div.nodes.first;
 
-    var m = toSymbols([
+    var m = toObservable([
       {'name': 'Raf'},
       {'name': 'Arv'},
       {'name': 'Neal'}
@@ -764,11 +764,11 @@
 
     assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']);
 
-    m.add(toSymbols({'name': 'Alex'}));
+    m.add(toObservable({'name': 'Alex'}));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal', 'Hi Alex']);
 
-    m.replaceRange(0, 2, toSymbols([{'name': 'Rafael'}, {'name': 'Erik'}]));
+    m.replaceRange(0, 2, toObservable([{'name': 'Rafael'}, {'name': 'Erik'}]));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Neal', 'Hi Alex']);
 
@@ -776,16 +776,16 @@
     deliverChanges(m);
     assertNodesAre(div, ['Hi Rafael', 'Hi Alex']);
 
-    m.insertAll(1, toSymbols([{'name': 'Erik'}, {'name': 'Dimitri'}]));
+    m.insertAll(1, toObservable([{'name': 'Erik'}, {'name': 'Dimitri'}]));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Rafael', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
 
-    m.replaceRange(0, 1, toSymbols([{'name': 'Tab'}, {'name': 'Neal'}]));
+    m.replaceRange(0, 1, toObservable([{'name': 'Tab'}, {'name': 'Neal'}]));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
 
     m.length = 0;
-    m.add(toSymbols({'name': 'Alex'}));
+    m.add(toObservable({'name': 'Alex'}));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Alex']);
   });
@@ -800,7 +800,7 @@
     expect(div.nodes.length, 1);
 
     t.attributes['iterate'] = '';
-    m = toSymbols({});
+    m = toObservable({});
     recursivelySetTemplateModel(div, m);
 
     deliverChanges(m);
@@ -811,7 +811,7 @@
     var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>');
     var t = div.nodes.first;
 
-    var m = toSymbols([
+    var m = toObservable([
       {'name': 'Raf'},
       {'name': 'Arv'},
       {'name': 'Neal'}
@@ -824,7 +824,7 @@
     var node2 = div.nodes[2];
     var node3 = div.nodes[3];
 
-    m.replaceRange(1, 2, toSymbols([{'name': 'Erik'}]));
+    m.replaceRange(1, 2, toObservable([{'name': 'Erik'}]));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Raf', 'Hi Erik', 'Hi Neal']);
     expect(div.nodes[1], node1,
@@ -835,7 +835,7 @@
         reason: 'model[2] did not change so the node should not have changed');
 
     node2 = div.nodes[2];
-    m.insert(0, toSymbols({'name': 'Alex'}));
+    m.insert(0, toObservable({'name': 'Alex'}));
     deliverChanges(m);
     assertNodesAre(div, ['Hi Alex', 'Hi Raf', 'Hi Erik', 'Hi Neal']);
   });
@@ -844,7 +844,7 @@
     var div = createTestHtml(
       '<template bind="{{}}"><span><span>{{ foo }}</span></span></template>');
 
-    var model = toSymbolMap({'foo': 'bar'});
+    var model = toObservable({'foo': 'bar'});
     recursivelySetTemplateModel(div, model);
     deliverChanges(model);
 
@@ -857,7 +857,7 @@
           '<input type="checkbox" checked="{{a}}">'
         '</template>');
     var t = div.nodes.first;
-    var m = toSymbols({
+    var m = toObservable({
       'a': true
     });
     t.bind('bind', m, '');
@@ -876,7 +876,7 @@
   nestedHelper(s, start) {
     var div = createTestHtml(s);
 
-    var m = toSymbols({
+    var m = toObservable({
       'a': {
         'b': 1,
         'c': {'d': 2}
@@ -891,11 +891,11 @@
     expect(div.nodes[i++].tagName, 'TEMPLATE');
     expect(div.nodes[i++].text, '2');
 
-    m[#a][#b] = 11;
+    m['a']['b'] = 11;
     deliverChanges(m);
     expect(div.nodes[start].text, '11');
 
-    m[#a][#c] = toSymbols({'d': 22});
+    m['a']['c'] = toObservable({'d': 22});
     deliverChanges(m);
     expect(div.nodes[start + 2].text, '22');
   }
@@ -922,7 +922,7 @@
   nestedIterateInstantiateHelper(s, start) {
     var div = createTestHtml(s);
 
-    var m = toSymbols({
+    var m = toObservable({
       'a': [
         {
           'b': 1,
@@ -946,7 +946,7 @@
     expect(div.nodes[i++].tagName, 'TEMPLATE');
     expect(div.nodes[i++].text, '22');
 
-    m[#a][1] = toSymbols({
+    m['a'][1] = toObservable({
       'b': 3,
       'c': {'d': 33}
     });
@@ -980,7 +980,7 @@
   nestedIterateIterateHelper(s, start) {
     var div = createTestHtml(s);
 
-    var m = toSymbols({
+    var m = toObservable({
       'a': [
         {
           'b': 1,
@@ -1006,7 +1006,7 @@
     expect(div.nodes[i++].text, '21');
     expect(div.nodes[i++].text, '22');
 
-    m[#a][1] = toSymbols({
+    m['a'][1] = toObservable({
       'b': 3,
       'c': [{'d': 31}, {'d': 32}, {'d': 33}]
     });
@@ -1047,7 +1047,7 @@
           '<template ref="t" repeat="{{items}}"></template>'
         '</template>');
 
-    var m = toSymbols([
+    var m = toObservable([
       {
         'name': 'Item 1',
         'items': [
@@ -1085,7 +1085,7 @@
     expect(div.nodes[i++].tagName, 'TEMPLATE');
     expect(div.nodes[i++].text, 'Item 2');
 
-    m[0] = toSymbols({'name': 'Item 1 changed'});
+    m[0] = toObservable({'name': 'Item 1 changed'});
 
     i = 1;
     deliverChanges(m);
@@ -1104,7 +1104,7 @@
           '</select>'
         '</template>');
 
-    var m = toSymbols({
+    var m = toObservable({
       'selected': 1,
       'groups': [{
         'name': 'one', 'items': [{ 'val': 0 }, { 'val': 1 }]
@@ -1146,7 +1146,7 @@
           '</template>'
         '</tbody></table>');
 
-    var m = toSymbols([
+    var m = toObservable([
       [{ 'val': 0 }, { 'val': 1 }],
       [{ 'val': 2 }, { 'val': 3 }]
     ]);
@@ -1183,7 +1183,7 @@
           '</tr>'
         '</tbody></table>');
 
-    var m = toSymbols([
+    var m = toObservable([
       [{ 'val': 0 }, { 'val': 1 }],
       [{ 'val': 2 }, { 'val': 3 }]
     ]);
@@ -1224,7 +1224,7 @@
           '</template>'
         '</ul>');
 
-    var m = toSymbols([
+    var m = toObservable([
       {
         'name': 'Item 1',
         'items': [
@@ -1252,7 +1252,7 @@
         '</p>'
       '</template>');
 
-    var m = toSymbols({
+    var m = toObservable({
       'a': {
         'b': {
           'c': 42
@@ -1279,7 +1279,7 @@
 
   observeTest('TemplateContentRemovedEmptyArray', () {
     var div = createTestHtml('<template iterate>Remove me</template>');
-    var model = toSymbols([]);
+    var model = toObservable([]);
 
     recursivelySetTemplateModel(div, model);
     deliverChanges(model);
@@ -1296,7 +1296,7 @@
           '</template>'
         '</template>');
 
-    var model = toSymbolMap({
+    var model = toObservable({
       'a': 1,
       'b': 2
     });
@@ -1313,7 +1313,7 @@
     var div = createTestHtml(
         '<template bind="{{}}" if="{{}}">{{ a }}</template>');
 
-    var model = toSymbolMap({'a': 42});
+    var model = toObservable({'a': 42});
     recursivelySetTemplateModel(div, model);
     deliverChanges(model);
     expect(div.nodes[1].text, '42');
@@ -1323,7 +1323,7 @@
     deliverChanges(model);
     expect(div.nodes.length, 1);
 
-    model = toSymbols({'a': 42});
+    model = toObservable({'a': 42});
     recursivelySetTemplateModel(div, model);
     deliverChanges(model);
     expect(div.nodes[1].text, '42');
@@ -1341,7 +1341,7 @@
           '</template>'
         '</template>');
 
-    var m = toSymbols({
+    var m = toObservable({
       'name': 'Hermes',
       'wife': {
         'name': 'LaBarbara'
@@ -1354,12 +1354,12 @@
     expect(div.nodes[1].text, 'Name: Hermes');
     expect(div.nodes[3].text, 'Wife: LaBarbara');
 
-    m[#child] = toSymbols({'name': 'Dwight'});
+    m['child'] = toObservable({'name': 'Dwight'});
     deliverChanges(m);
     expect(div.nodes.length, 6);
     expect(div.nodes[5].text, 'Child: Dwight');
 
-    m.remove(#wife);
+    m.remove('wife');
     deliverChanges(m);
     expect(div.nodes.length, 5);
     expect(div.nodes[4].text, 'Child: Dwight');
@@ -1372,7 +1372,7 @@
           '<template bind="{{friend}}" if="{{friend}}" ref="t"></template>'
         '</template>');
 
-    var m = toSymbols({
+    var m = toObservable({
       'name': 'Fry',
       'friend': {
         'name': 'Bender'
@@ -1385,12 +1385,12 @@
     expect(div.nodes[1].text, 'Name: Fry');
     expect(div.nodes[3].text, 'Name: Bender');
 
-    m[#friend][#friend] = toSymbols({'name': 'Leela'});
+    m['friend']['friend'] = toObservable({'name': 'Leela'});
     deliverChanges(m);
     expect(div.nodes.length, 7);
     expect(div.nodes[5].text, 'Name: Leela');
 
-    m[#friend] = toSymbols({'name': 'Leela'});
+    m['friend'] = toObservable({'name': 'Leela'});
     deliverChanges(m);
     expect(div.nodes.length, 5);
     expect(div.nodes[3].text, 'Name: Leela');
@@ -1402,11 +1402,11 @@
           '<template bind></template>'
         '</template>');
 
-    var m = toSymbols([{ 'foo': 'bar' }]);
+    var m = toObservable([{ 'foo': 'bar' }]);
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
 
-    m.add(toSymbols({ 'foo': 'baz' }));
+    m.add(toObservable({ 'foo': 'baz' }));
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
 
@@ -1420,7 +1420,7 @@
 
     var div = createTestHtml('<template repeat>{{ foo }}</template>');
 
-    var m = toSymbols([{ 'foo': 'bar' }, { 'foo': 'bat'}]);
+    var m = toObservable([{ 'foo': 'bar' }, { 'foo': 'bat'}]);
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
 
@@ -1441,7 +1441,7 @@
           '<template bind ref=src></template>'
         '</template>');
 
-    var m = toSymbols({'foo': 'bar'});
+    var m = toObservable({'foo': 'bar'});
     recursivelySetTemplateModel(div, m);
     performMicrotaskCheckpoint();
 
@@ -1459,7 +1459,7 @@
     // Note: this test data is a little different from the JS version, because
     // we allow binding to the "length" field of the Map in preference to
     // binding keys.
-    var m = toSymbols({
+    var m = toObservable({
       'a': [
         [],
         { 'b': [1,2,3,4] },
@@ -1496,7 +1496,7 @@
         '<template repeat="{{}}">'
           '<template ref="a" bind="{{}}"></template>'
         '</template>');
-    var model = toSymbols([]);
+    var model = toObservable([]);
     recursivelySetTemplateModel(div, model);
     deliverChanges(model);
 
@@ -1523,17 +1523,17 @@
     var contentB = templateB.content;
     expect(contentA, isNotNull);
 
-    expect(templateA.document, isNot(equals(contentA.document)));
-    expect(templateB.document, isNot(equals(contentB.document)));
+    expect(templateA.ownerDocument, isNot(equals(contentA.ownerDocument)));
+    expect(templateB.ownerDocument, isNot(equals(contentB.ownerDocument)));
 
-    expect(templateB.document, templateA.document);
-    expect(contentB.document, contentA.document);
+    expect(templateB.ownerDocument, templateA.ownerDocument);
+    expect(contentB.ownerDocument, contentA.ownerDocument);
 
-    expect(templateA.document.window, window);
-    expect(templateB.document.window, window);
+    expect(templateA.ownerDocument.window, window);
+    expect(templateB.ownerDocument.window, window);
 
-    expect(contentA.document.window, null);
-    expect(contentB.document.window, null);
+    expect(contentA.ownerDocument.window, null);
+    expect(contentB.ownerDocument.window, null);
 
     expect(contentA.nodes.last, contentA.nodes.first);
     expect(contentA.nodes.first.tagName, 'A');
@@ -1550,15 +1550,15 @@
     var templateA = div.nodes.first;
     var templateB = templateA.content.nodes.first;
 
-    expect(templateB.document, templateA.content.document);
-    expect(templateB.content.document, templateA.content.document);
+    expect(templateB.ownerDocument, templateA.content.ownerDocument);
+    expect(templateB.content.ownerDocument, templateA.content.ownerDocument);
   });
 
   observeTest('BindShadowDOM', () {
     if (ShadowRoot.supported) {
       var root = createShadowTestHtml(
           '<template bind="{{}}">Hi {{ name }}</template>');
-      var model = toSymbolMap({'name': 'Leela'});
+      var model = toObservable({'name': 'Leela'});
       recursivelySetTemplateModel(root, model);
       deliverChanges(model);
       expect(root.nodes[1].text, 'Hi Leela');
@@ -1567,7 +1567,7 @@
 
   observeTest('BindShadowDOM createInstance', () {
     if (ShadowRoot.supported) {
-      var model = toSymbolMap({'name': 'Leela'});
+      var model = toObservable({'name': 'Leela'});
       var template = new Element.html('<template>Hi {{ name }}</template>');
       var root = createShadowTestHtml('');
       root.nodes.add(template.createInstance(model));
@@ -1575,7 +1575,7 @@
       performMicrotaskCheckpoint();
       expect(root.text, 'Hi Leela');
 
-      model[#name] = 'Fry';
+      model['name'] = 'Fry';
       performMicrotaskCheckpoint();
       expect(root.text, 'Hi Fry');
     }
@@ -1585,7 +1585,7 @@
     if (ShadowRoot.supported) {
       var root = createShadowTestHtml(
           '<template id=foo>Hi</template><template bind ref=foo></template>');
-      recursivelySetTemplateModel(root, toSymbolMap({}));
+      recursivelySetTemplateModel(root, toObservable({}));
       performMicrotaskCheckpoint();
       expect(root.nodes.length, 3);
     }
@@ -1601,7 +1601,7 @@
       '</template>');
 
     var syntax = new UnbindingInNestedBindSyntax();
-    var model = toSymbolMap({
+    var model = toObservable({
       'outer': {
         'inner': {
           'age': 42
@@ -1614,13 +1614,13 @@
     deliverChanges(model);
     expect(syntax.count, 1);
 
-    var inner = model[#outer][#inner];
-    model[#outer] = null;
+    var inner = model['outer']['inner'];
+    model['outer'] = null;
 
     deliverChanges(model);
     expect(syntax.count, 1);
 
-    model[#outer] = toSymbols({'inner': {'age': 2}});
+    model['outer'] = toObservable({'inner': {'age': 2}});
     syntax.expectedAge = 2;
 
     deliverChanges(model);
@@ -1646,7 +1646,7 @@
         '</template>'
       '</template>');
     var outer = div.nodes.first;
-    var model = toSymbolMap({'b': {'foo': 'bar'}});
+    var model = toObservable({'b': {'foo': 'bar'}});
 
     var host = new DivElement();
     var instance = outer.createInstance(model, new TestBindingSyntax());
@@ -1726,7 +1726,7 @@
     if (name != 'text' || path != 'age')
       return;
 
-    expect(model[#age], expectedAge);
+    expect(model['age'], expectedAge);
     count++;
   }
 }
@@ -1743,8 +1743,8 @@
 void expectObservable(model) {
   if (model is! Observable) {
     // This is here to eagerly catch a bug in the test; it means the test
-    // forgot a toSymbols somewhere.
-    expect(identical(toSymbols(model), model), true,
+    // forgot a toObservable somewhere.
+    expect(identical(toObservable(model), model), true,
         reason: 'model type "${model.runtimeType}" should be observable');
     return;
   }
@@ -1760,8 +1760,6 @@
   }
 }
 
-toSymbols(obj) => toObservable(_deepToSymbol(obj));
-
 _deepToSymbol(value) {
   if (value is Map) {
     var result = new LinkedHashMap();
diff --git a/pkg/observe/lib/html.dart b/pkg/observe/lib/html.dart
index 4ba0154..abf333a 100644
--- a/pkg/observe/lib/html.dart
+++ b/pkg/observe/lib/html.dart
@@ -16,7 +16,9 @@
 /** An observable version of [window.location.hash]. */
 final ObservableLocationHash windowLocation = new ObservableLocationHash._();
 
-class ObservableLocationHash extends ChangeNotifierBase {
+class ObservableLocationHash extends ChangeNotifier {
+  Object _currentHash;
+
   ObservableLocationHash._() {
     // listen on changes to #hash in the URL
     // Note: listen on both popState and hashChange, because IE9 doesn't support
@@ -25,6 +27,8 @@
     // changes.
     window.onHashChange.listen(_notifyHashChange);
     window.onPopState.listen(_notifyHashChange);
+
+    _currentHash = hash;
   }
 
   @reflectable String get hash => window.location.hash;
@@ -41,7 +45,9 @@
   }
 
   void _notifyHashChange(_) {
-    notifyChange(new PropertyChangeRecord(#hash));
+    var oldValue = _currentHash;
+    _currentHash = hash;
+    notifyPropertyChange(#hash, oldValue, _currentHash);
   }
 }
 
diff --git a/pkg/observe/lib/observe.dart b/pkg/observe/lib/observe.dart
index 29d868e..abce718 100644
--- a/pkg/observe/lib/observe.dart
+++ b/pkg/observe/lib/observe.dart
@@ -13,7 +13,7 @@
  * You can provide an observable object in two ways. The simplest way is to
  * use dirty checking to discover changes automatically:
  *
- *     class Monster extends Unit with ObservableMixin {
+ *     class Monster extends Unit with Observable {
  *       @observable int health = 100;
  *
  *       void damage(int amount) {
@@ -41,7 +41,7 @@
  * manually. This avoids the potentially expensive [Observable.dirtyCheck]
  * operation, but requires more work in the object:
  *
- *     class Monster extends Unit with ChangeNotifierMixin {
+ *     class Monster extends Unit with ChangeNotifier {
  *       int _health = 100;
  *       @reflectable get health => _health;
  *       @reflectable set health(val) {
@@ -88,6 +88,8 @@
     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
diff --git a/pkg/observe/lib/src/bind_property.dart b/pkg/observe/lib/src/bind_property.dart
index a8e78de..a31d1ab 100644
--- a/pkg/observe/lib/src/bind_property.dart
+++ b/pkg/observe/lib/src/bind_property.dart
@@ -7,7 +7,7 @@
 /**
  * Forwards an observable property from one object to another. For example:
  *
- *     class MyModel extends ObservableBase {
+ *     class MyModel extends Observable {
  *       StreamSubscription _sub;
  *       MyOtherModel _otherModel;
  *
@@ -28,8 +28,10 @@
     void callback()) {
   return source.changes.listen((records) {
     for (var record in records) {
-      if (record.changes(sourceName)) {
+      if (record is PropertyChangeRecord &&
+          (record as PropertyChangeRecord).name == sourceName) {
         callback();
+        break;
       }
     }
   });
diff --git a/pkg/observe/lib/src/change_notifier.dart b/pkg/observe/lib/src/change_notifier.dart
index 5e08f33..a51fda6 100644
--- a/pkg/observe/lib/src/change_notifier.dart
+++ b/pkg/observe/lib/src/change_notifier.dart
@@ -5,22 +5,14 @@
 part of observe;
 
 /**
- * Base class implementing [Observable] object that performs its own change
- * notifications, and does not need to be considered by [Observable.dirtyCheck].
+ * Mixin and base class for implementing an [Observable] object that performs
+ * its own change notifications, and does not need to be considered by
+ * [Observable.dirtyCheck].
  *
  * When a field, property, or indexable item is changed, a derived class should
  * call [notifyPropertyChange]. See that method for an example.
  */
-class ChangeNotifierBase = Object with ChangeNotifierMixin;
-
-/**
- * Mixin implementing [Observable] object that performs its own change
- * notifications, and does not need to be considered by [Observable.dirtyCheck].
- *
- * When a field, property, or indexable item is changed, a derived class should
- * call [notifyPropertyChange]. See that method for an example.
- */
-abstract class ChangeNotifierMixin implements Observable {
+abstract class ChangeNotifier implements Observable {
   StreamController _changes;
   List<ChangeRecord> _records;
 
@@ -65,7 +57,7 @@
    * Notify that the field [name] of this object has been changed.
    *
    * The [oldValue] and [newValue] are also recorded. If the two values are
-   * identical, no change will be recorded.
+   * equal, no change will be recorded.
    *
    * For convenience this returns [newValue]. This makes it easy to use in a
    * setter:
diff --git a/pkg/observe/lib/src/change_record.dart b/pkg/observe/lib/src/change_record.dart
index 99e806d..bb584e8 100644
--- a/pkg/observe/lib/src/change_record.dart
+++ b/pkg/observe/lib/src/change_record.dart
@@ -5,22 +5,41 @@
 part of observe;
 
 /** Records a change to an [Observable]. */
-abstract class ChangeRecord {
-  // TODO(jmesserly): rename this--it's confusing. Perhaps "matches"?
-  /** True if the change affected the given item, otherwise false. */
-  bool changes(key);
-}
+// TODO(jmesserly): remove this type
+abstract class ChangeRecord {}
 
 /** A change record to a field of an observable object. */
-class PropertyChangeRecord extends ChangeRecord {
-  /** The field that was changed. */
-  final Symbol field;
+class PropertyChangeRecord<T> extends ChangeRecord {
+  /**
+   * *Deprecated* use [name] instead.
+   * The field that was changed.
+   */
+  @deprecated
+  Symbol get field => name;
 
-  PropertyChangeRecord(this.field);
+  /** The object that changed. */
+  final object;
 
-  bool changes(key) => key is Symbol && field == key;
+  /** The name of the property that changed. */
+  final Symbol name;
 
-  String toString() => '#<PropertyChangeRecord $field>';
+  /** The previous value of the property. */
+  final T oldValue;
+
+  /** The new value of the property. */
+  final T newValue;
+
+  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>';
 }
 
 /** A change record for an observable list. */
@@ -41,16 +60,23 @@
     }
   }
 
+  /**
+   * *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 changes(key) {
+  bool indexChanged(otherIndex) {
     // If key isn't an int, or before the index, then it wasn't changed.
-    if (key is! int || key < index) return false;
+    if (otherIndex is! int || otherIndex < index) return false;
 
     // If this was a shift operation, anything after index is changed.
     if (addedCount != removedCount) return true;
 
     // Otherwise, anything in the update range was changed.
-    return key < index + addedCount;
+    return otherIndex < index + addedCount;
   }
 
   String toString() => '#<ListChangeRecord index: $index, '
diff --git a/pkg/observe/lib/src/compound_binding.dart b/pkg/observe/lib/src/compound_binding.dart
index a619586..3d27926 100644
--- a/pkg/observe/lib/src/compound_binding.dart
+++ b/pkg/observe/lib/src/compound_binding.dart
@@ -27,7 +27,7 @@
  *     binding.bind('nameN', objN, pathN);
  */
 // TODO(jmesserly): rename to something that indicates it's a computed value?
-class CompoundBinding extends ChangeNotifierBase {
+class CompoundBinding extends ChangeNotifier {
   CompoundBindingCombinator _combinator;
 
   // TODO(jmesserly): ideally these would be String keys, but sometimes we
diff --git a/pkg/observe/lib/src/dirty_check.dart b/pkg/observe/lib/src/dirty_check.dart
index b564ab6c..386ad60 100644
--- a/pkg/observe/lib/src/dirty_check.dart
+++ b/pkg/observe/lib/src/dirty_check.dart
@@ -35,7 +35,7 @@
  * Synchronously deliver all change records for known observables.
  *
  * This will execute [Observable.deliverChanges] on objects that inherit from
- * [ObservableMixin].
+ * [Observable].
  */
 // Note: this is called performMicrotaskCheckpoint in change_summary.js.
 void dirtyCheckObservables() {
diff --git a/pkg/observe/lib/src/list_path_observer.dart b/pkg/observe/lib/src/list_path_observer.dart
index f7e620f..f882e12 100644
--- a/pkg/observe/lib/src/list_path_observer.dart
+++ b/pkg/observe/lib/src/list_path_observer.dart
@@ -11,7 +11,7 @@
 /**
  * Observes a path starting from each item in the list.
  */
-class ListPathObserver<E, P> extends ChangeNotifierBase {
+class ListPathObserver<E, P> extends ChangeNotifier {
   final ObservableList<E> list;
   final String _itemPath;
   final List<PathObserver> _observers = <PathObserver>[];
@@ -46,8 +46,8 @@
 
   void _reduce() {
     _scheduled = false;
-    _value = _observers.map((o) => o.value);
-    notifyChange(new PropertyChangeRecord(#value));
+    var newValue = _observers.map((o) => o.value);
+    _value = notifyPropertyChange(#value, _value, newValue);
   }
 
   void _scheduleReduce(_) {
diff --git a/pkg/observe/lib/src/metadata.dart b/pkg/observe/lib/src/metadata.dart
index f8ec5a3..48d06c2 100644
--- a/pkg/observe/lib/src/metadata.dart
+++ b/pkg/observe/lib/src/metadata.dart
@@ -39,7 +39,7 @@
  * it available to [PathObserver] at runtime. For example:
  *
  *     @reflectable
- *     class Monster extends ChangeNotifierBase {
+ *     class Monster extends ChangeNotifier {
  *       int _health;
  *       int get health => _health;
  *       ...
diff --git a/pkg/observe/lib/src/observable.dart b/pkg/observe/lib/src/observable.dart
index f87de36..ca94085 100644
--- a/pkg/observe/lib/src/observable.dart
+++ b/pkg/observe/lib/src/observable.dart
@@ -5,87 +5,27 @@
 part of observe;
 
 /**
- * Interface representing an observable object. This is used by data in
- * model-view architectures to notify interested parties of [changes].
+ * Represents an object with observable properties. This is used by data in
+ * model-view architectures to notify interested parties of [changes] to the
+ * object's properties (fields or getter/setter pairs).
  *
- * This object does not require any specific technique to implement
- * observability. If you mixin [ObservableMixin], [dirtyCheck] will know to
- * check for changes on the object. You may also implement change notification
- * yourself, by calling [notifyChange].
+ * The interface does not require any specific technique to implement
+ * observability. You can implement it in the following ways:
  *
- * You can use [ObservableBase] or [ObservableMixin] to implement this.
+ * - extend or mixin this class, and let the application call [dirtyCheck]
+ *   periodically to check for changes to your object.
+ * - extend or mixin [ChangeNotifier], and implement change notifications
+ *   manually by calling [notifyPropertyChange] from your setters.
+ * - implement this interface and provide your own implementation.
  */
 abstract class Observable {
   /**
-   * The stream of change records to this object. Records will be delivered
-   * asynchronously.
-   *
-   * [deliverChanges] can be called to force synchronous delivery.
-   */
-  Stream<List<ChangeRecord>> get changes;
-
-  /**
-   * Synchronously deliver pending [changes]. Returns true if any records were
-   * delivered, otherwise false.
-   */
-  // TODO(jmesserly): this is a bit different from the ES Harmony version, which
-  // allows delivery of changes to a particular observer:
-  // http://wiki.ecmascript.org/doku.php?id=harmony:observe#object.deliverchangerecords
-  //
-  // The rationale for that, and for async delivery in general, is the principal
-  // that you shouldn't run code (observers) when it doesn't expect to be run.
-  // If you do that, you risk violating invariants that the code assumes.
-  //
-  // For this reason, we need to match the ES Harmony version. The way we can do
-  // this in Dart is to add a method on StreamSubscription (possibly by
-  // subclassing Stream* types) that immediately delivers records for only
-  // that subscription. Alternatively, we could consider using something other
-  // than Stream to deliver the multicast change records, and provide an
-  // Observable->Stream adapter.
-  //
-  // Also: we should be delivering changes to the observer (subscription) based
-  // on the birth order of the observer. This is for compatibility with ES
-  // Harmony as well as predictability for app developers.
-  bool deliverChanges();
-
-  /**
-   * Notify observers of a change.
-   *
-   * For most objects [ObservableMixin.notifyPropertyChange] is more
-   * convenient, but collections sometimes deliver other types of changes such
-   * as a [ListChangeRecord].
-   */
-  void notifyChange(ChangeRecord record);
-
-  /**
-   * True if this object has any observers, and should call
-   * [notifyChange] for changes.
-   */
-  bool get hasObservers;
-
-  /**
-   * Performs dirty checking of objects that inherit from [ObservableMixin].
+   * Performs dirty checking of objects that inherit from [Observable].
    * This scans all observed objects using mirrors and determines if any fields
    * have changed. If they have, it delivers the changes for the object.
    */
   static void dirtyCheck() => dirtyCheckObservables();
-}
 
-/**
- * Base class implementing [Observable].
- *
- * When a field, property, or indexable item is changed, the change record
- * will be sent to [changes].
- */
-class ObservableBase = Object with ObservableMixin;
-
-/**
- * Mixin for implementing [Observable] objects.
- *
- * When a field, property, or indexable item is changed, the change record
- * will be sent to [changes].
- */
-abstract class ObservableMixin implements Observable {
   StreamController _changes;
   InstanceMirror _mirror;
 
@@ -94,6 +34,12 @@
 
   static final _objectType = reflectClass(Object);
 
+  /**
+   * The stream of change records to this object. Records will be delivered
+   * asynchronously.
+   *
+   * [deliverChanges] can be called to force synchronous delivery.
+   */
   Stream<List<ChangeRecord>> get changes {
     if (_changes == null) {
       _changes = new StreamController.broadcast(sync: true,
@@ -102,6 +48,10 @@
     return _changes.stream;
   }
 
+  /**
+   * True if this object has any observers, and should call
+   * [notifyChange] for changes.
+   */
   bool get hasObservers => _changes != null && _changes.hasListener;
 
   void _observed() {
@@ -144,6 +94,28 @@
     }
   }
 
+  /**
+   * Synchronously deliver pending [changes]. Returns true if any records were
+   * delivered, otherwise false.
+   */
+  // TODO(jmesserly): this is a bit different from the ES Harmony version, which
+  // allows delivery of changes to a particular observer:
+  // http://wiki.ecmascript.org/doku.php?id=harmony:observe#object.deliverchangerecords
+  //
+  // The rationale for that, and for async delivery in general, is the principal
+  // that you shouldn't run code (observers) when it doesn't expect to be run.
+  // If you do that, you risk violating invariants that the code assumes.
+  //
+  // For this reason, we need to match the ES Harmony version. The way we can do
+  // this in Dart is to add a method on StreamSubscription (possibly by
+  // subclassing Stream* types) that immediately delivers records for only
+  // that subscription. Alternatively, we could consider using something other
+  // than Stream to deliver the multicast change records, and provide an
+  // Observable->Stream adapter.
+  //
+  // Also: we should be delivering changes to the observer (subscription) based
+  // on the birth order of the observer. This is for compatibility with ES
+  // Harmony as well as predictability for app developers.
   bool deliverChanges() {
     if (_values == null || !hasObservers) return false;
 
@@ -154,9 +126,9 @@
 
     _values.forEach((name, oldValue) {
       var newValue = _mirror.getField(name).reflectee;
-      if (!identical(oldValue, newValue)) {
+      if (oldValue != newValue) {
         if (records == null) records = [];
-        records.add(new PropertyChangeRecord(name));
+        records.add(new PropertyChangeRecord(this, name, oldValue, newValue));
         _values[name] = newValue;
       }
     });
@@ -171,7 +143,7 @@
    * Notify that the field [name] of this object has been changed.
    *
    * The [oldValue] and [newValue] are also recorded. If the two values are
-   * identical, no change will be recorded.
+   * equal, no change will be recorded.
    *
    * For convenience this returns [newValue].
    */
@@ -179,9 +151,17 @@
       => _notifyPropertyChange(this, field, oldValue, newValue);
 
   /**
-   * Notify a change manually. This is *not* required for fields, but can be
-   * used for computed properties. *Note*: unlike [ChangeNotifierMixin] this
-   * will not schedule [deliverChanges]; use [Observable.dirtyCheck] instead.
+   * Notify observers of a change.
+   *
+   * For most objects [Observable.notifyPropertyChange] is more convenient, but
+   * collections sometimes deliver other types of changes such as a
+   * [ListChangeRecord].
+   *
+   * Notes:
+   * - This is *not* required for fields if you mixin or extend [Observable],
+   *   but you can use it for computed properties.
+   * - Unlike [ChangeNotifier] this will not schedule [deliverChanges]; use
+   *   [Observable.dirtyCheck] instead.
    */
   void notifyChange(ChangeRecord record) {
     if (!hasObservers) return;
@@ -192,12 +172,18 @@
 }
 
 /**
+ * *Deprecated* use [Observable.notifyPropertyChange] instead.
+ *
+ * This API should not be used as it creates a
+ * [PropertyChangeRecord] without oldValue and newValue.
+ *
  * Notify the property change. Shorthand for:
  *
- *     target.notifyChange(new PropertyChangeRecord(targetName));
+ *     target.notifyChange(new PropertyChangeRecord(target, name, null, null));
  */
-void notifyProperty(Observable target, Symbol targetName) {
-  target.notifyChange(new PropertyChangeRecord(targetName));
+@deprecated
+void notifyProperty(Observable target, Symbol name) {
+  target.notifyChange(new PropertyChangeRecord(target, name, null, null));
 }
 
 // TODO(jmesserly): remove the instance method and make this top-level method
@@ -205,10 +191,8 @@
 _notifyPropertyChange(Observable obj, Symbol field, Object oldValue,
     Object newValue) {
 
-  // TODO(jmesserly): should this be == instead of identical, to prevent
-  // spurious loops?
-  if (obj.hasObservers && !identical(oldValue, newValue)) {
-    obj.notifyChange(new PropertyChangeRecord(field));
+  if (obj.hasObservers && oldValue != newValue) {
+    obj.notifyChange(new PropertyChangeRecord(obj, field, oldValue, newValue));
   }
   return newValue;
 }
diff --git a/pkg/observe/lib/src/observable_box.dart b/pkg/observe/lib/src/observable_box.dart
index 1bdf4cc..7db72bf 100644
--- a/pkg/observe/lib/src/observable_box.dart
+++ b/pkg/observe/lib/src/observable_box.dart
@@ -10,9 +10,9 @@
  * An observable box that holds a value. Use this if you want to store a single
  * value. For other cases, it is better to use [ObservableList],
  * [ObservableMap], or a custom [Observable] implementation based on
- * [ObservableMixin]. The property name for changes is "value".
+ * [Observable]. The property name for changes is "value".
  */
-class ObservableBox<T> extends ChangeNotifierBase {
+class ObservableBox<T> extends ChangeNotifier {
   T _value;
 
   ObservableBox([T initialValue]) : _value = initialValue;
diff --git a/pkg/observe/lib/src/observable_list.dart b/pkg/observe/lib/src/observable_list.dart
index a79ed64..0cf181c 100644
--- a/pkg/observe/lib/src/observable_list.dart
+++ b/pkg/observe/lib/src/observable_list.dart
@@ -9,7 +9,7 @@
  * removed, or replaced, then observers that are listening to [changes]
  * will be notified.
  */
-class ObservableList<E> extends ListBase<E> with ChangeNotifierMixin {
+class ObservableList<E> extends ListBase<E> with ChangeNotifier {
   List<ListChangeRecord> _listRecords;
 
   /** The inner [List<E>] with the actual storage. */
diff --git a/pkg/observe/lib/src/observable_map.dart b/pkg/observe/lib/src/observable_map.dart
index da8b614..d4da646 100644
--- a/pkg/observe/lib/src/observable_map.dart
+++ b/pkg/observe/lib/src/observable_map.dart
@@ -11,30 +11,41 @@
 // backing store.
 
 // TODO(jmesserly): should we summarize map changes like we do for list changes?
-class MapChangeRecord extends ChangeRecord {
-  /** The map key that changed. */
-  final key;
+class MapChangeRecord<K, V> extends ChangeRecord {
+  // TODO(jmesserly): we could store this more compactly if it matters, with
+  // subtypes for inserted and removed.
 
-  // TODO(jmesserly): we could store this more compactly if it matters.
+  /** The map key that changed. */
+  final K key;
+
+  /** The previous value associated with this key. */
+  final V oldValue;
+
+  /** The new value associated with this key. */
+  final V newValue;
+
   /** True if this key was inserted. */
   final bool isInsert;
 
   /** True if this key was removed. */
   final bool isRemove;
 
-  MapChangeRecord(this.key, {this.isInsert: false, this.isRemove: false}) {
-    if (isInsert && isRemove) {
-      throw new ArgumentError(
-          '$key cannot be inserted and removed in the same change');
-    }
-  }
+  MapChangeRecord(this.key, this.oldValue, this.newValue)
+      : isInsert = false, isRemove = false;
 
-  // Use == on the key, to match equality semantics of most Maps.
+  MapChangeRecord.insert(this.key, this.newValue)
+      : isInsert = true, isRemove = false;
+
+  MapChangeRecord.remove(this.key, this.oldValue)
+      : isInsert = false, isRemove = true;
+
+  /// *Deprecated* compare [key]s instead.
+  @deprecated
   bool changes(otherKey) => key == otherKey;
 
   String toString() {
     var kind = isInsert ? 'insert' : isRemove ? 'remove' : 'set';
-    return '#<MapChangeRecord $kind $key>';
+    return '#<MapChangeRecord $kind $key from: $oldValue to: $newValue>';
   }
 }
 
@@ -43,7 +54,7 @@
  * removed, or replaced, then observers that are listening to [changes]
  * will be notified.
  */
-class ObservableMap<K, V> extends ChangeNotifierBase implements Map<K, V> {
+class ObservableMap<K, V> extends ChangeNotifier implements Map<K, V> {
   final Map<K, V> _map;
 
   /** Creates an observable map. */
@@ -103,9 +114,9 @@
     if (hasObservers) {
       if (len != _map.length) {
         notifyPropertyChange(#length, len, _map.length);
-        notifyChange(new MapChangeRecord(key, isInsert: true));
-      } else if (!identical(oldValue, value)) {
-        notifyChange(new MapChangeRecord(key));
+        notifyChange(new MapChangeRecord.insert(key, value));
+      } else if (oldValue != value) {
+        notifyChange(new MapChangeRecord(key, oldValue, value));
       }
     }
   }
@@ -119,7 +130,7 @@
     V result = _map.putIfAbsent(key, ifAbsent);
     if (hasObservers && len != _map.length) {
       notifyPropertyChange(#length, len, _map.length);
-      notifyChange(new MapChangeRecord(key, isInsert: true));
+      notifyChange(new MapChangeRecord.insert(key, result));
     }
     return result;
   }
@@ -128,7 +139,7 @@
     int len = _map.length;
     V result =  _map.remove(key);
     if (hasObservers && len != _map.length) {
-      notifyChange(new MapChangeRecord(key, isRemove: true));
+      notifyChange(new MapChangeRecord.remove(key, result));
       notifyPropertyChange(#length, len, _map.length);
     }
     return result;
@@ -138,7 +149,7 @@
     int len = _map.length;
     if (hasObservers && len > 0) {
       _map.forEach((key, value) {
-        notifyChange(new MapChangeRecord(key, isRemove: true));
+        notifyChange(new MapChangeRecord.remove(key, value));
       });
       notifyPropertyChange(#length, len, 0);
     }
diff --git a/pkg/observe/lib/src/path_observer.dart b/pkg/observe/lib/src/path_observer.dart
index c6e0be0..1b6e1a3 100644
--- a/pkg/observe/lib/src/path_observer.dart
+++ b/pkg/observe/lib/src/path_observer.dart
@@ -21,7 +21,7 @@
  *
  * This class is used to implement [Node.bind] and similar functionality.
  */
-class PathObserver extends ChangeNotifierBase {
+class PathObserver extends ChangeNotifier {
   /** The path string. */
   final String path;
 
@@ -119,21 +119,19 @@
   }
 
   void _updateObservedValues([int start = 0]) {
-    bool changed = false;
+    var oldValue, newValue;
     for (int i = start; i < _segments.length; i++) {
-      final newValue = _getObjectProperty(_values[i], _segments[i]);
-      if (identical(_values[i + 1], newValue)) {
+      oldValue = _values[i + 1];
+      newValue = _getObjectProperty(_values[i], _segments[i]);
+      if (identical(oldValue, newValue)) {
         _observePath(start, i);
         return;
       }
       _values[i + 1] = newValue;
-      changed = true;
     }
 
     _observePath(start);
-    if (changed) {
-      notifyChange(new PropertyChangeRecord(#value));
-    }
+    notifyPropertyChange(#value, oldValue, newValue);
   }
 
   void _observePath([int start = 0, int end]) {
@@ -160,7 +158,7 @@
         }
 
         for (var record in records) {
-          if (record.changes(_segments[i])) {
+          if (_changeRecordMatches(record, _segments[i])) {
             _updateObservedValues(i);
             return;
           }
@@ -170,6 +168,20 @@
   }
 }
 
+bool _changeRecordMatches(record, key) {
+  if (record is ListChangeRecord) {
+    return key is int && (record as ListChangeRecord).indexChanged(key);
+  }
+  if (record is PropertyChangeRecord) {
+    return (record as PropertyChangeRecord).name == key;
+  }
+  if (record is MapChangeRecord) {
+    if (key is Symbol) key = MirrorSystem.getName(key);
+    return (record as MapChangeRecord).key == key;
+  }
+  return false;
+}
+
 _getObjectProperty(object, property) {
   if (object == null) {
     return null;
@@ -185,12 +197,12 @@
 
   if (property is Symbol) {
     var mirror = reflect(object);
-    try {
-      return mirror.getField(property).reflectee;
-    } catch (e) {}
+    var result = _tryGetField(mirror, property);
+    if (result != null) return result.reflectee;
   }
 
   if (object is Map) {
+    if (property is Symbol) property = MirrorSystem.getName(property);
     return object[property];
   }
 
@@ -209,13 +221,11 @@
 
   if (property is Symbol) {
     var mirror = reflect(object);
-    try {
-      mirror.setField(property, value);
-      return true;
-    } catch (e) {}
+    if (_trySetField(mirror, property, value)) return true;
   }
 
   if (object is Map) {
+    if (property is Symbol) property = MirrorSystem.getName(property);
     object[property] = value;
     return true;
   }
@@ -223,6 +233,58 @@
   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 _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;
+  }
+}
+
+// TODO(jmesserly): workaround for:
+// https://code.google.com/p/dart/issues/detail?id=10029
+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;
+    }
+  }
+  return false;
+}
 
 // From: https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
 
diff --git a/pkg/observe/lib/transform.dart b/pkg/observe/lib/transform.dart
index ecf4353..3e0aac2 100644
--- a/pkg/observe/lib/transform.dart
+++ b/pkg/observe/lib/transform.dart
@@ -138,10 +138,10 @@
   var declaresObservable = false;
   if (cls.extendsClause != null) {
     var id = _getSimpleIdentifier(cls.extendsClause.superclass.name);
-    if (id.name == 'ObservableBase') {
-      code.edit(id.offset, id.end, 'ChangeNotifierBase');
+    if (id.name == 'Observable') {
+      code.edit(id.offset, id.end, 'ChangeNotifier');
       declaresObservable = true;
-    } else if (id.name == 'ChangeNotifierBase') {
+    } else if (id.name == 'ChangeNotifier') {
       declaresObservable = true;
     } else if (id.name != 'HtmlElement' && id.name != 'CustomElement'
         && id.name != 'Object') {
@@ -154,11 +154,11 @@
   if (cls.withClause != null) {
     for (var type in cls.withClause.mixinTypes) {
       var id = _getSimpleIdentifier(type.name);
-      if (id.name == 'ObservableMixin') {
-        code.edit(id.offset, id.end, 'ChangeNotifierMixin');
+      if (id.name == 'Observable') {
+        code.edit(id.offset, id.end, 'ChangeNotifier');
         declaresObservable = true;
         break;
-      } else if (id.name == 'ChangeNotifierMixin') {
+      } else if (id.name == 'ChangeNotifier') {
         declaresObservable = true;
         break;
       } else {
@@ -194,7 +194,7 @@
         if (!declaresObservable) {
           logger.warning('Observable fields should be put in an observable '
               'objects. Please declare that this class extends from '
-              'ObservableBase, includes ObservableMixin, or implements '
+              'Observable, includes Observable, or implements '
               'Observable.',
               span: _getSpan(file, member));
         }
diff --git a/pkg/observe/pubspec.yaml b/pkg/observe/pubspec.yaml
index 8fbfb39..3f0b32f 100644
--- a/pkg/observe/pubspec.yaml
+++ b/pkg/observe/pubspec.yaml
@@ -11,6 +11,7 @@
   analyzer_experimental: any
   barback: any
   logging: any
+  meta: any
   path: any
   source_maps: any
 dev_dependencies:
diff --git a/pkg/observe/test/observable_list_test.dart b/pkg/observe/test/observable_list_test.dart
index 43527e0..ab736a3 100644
--- a/pkg/observe/test/observable_list_test.dart
+++ b/pkg/observe/test/observable_list_test.dart
@@ -23,7 +23,7 @@
       list = toObservable([1, 2, 3]);
       changes = null;
       sub = list.changes.listen((records) {
-        changes = records.where((r) => r.changes(#length)).toList();
+        changes = getPropertyChangeRecords(records, #length);
       });
     });
 
@@ -33,7 +33,7 @@
       list.add(4);
       expect(list, [1, 2, 3, 4]);
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(list, 3, 4)]);
     });
 
     observeTest('removeObject', () {
@@ -41,7 +41,7 @@
       expect(list, orderedEquals([1, 3]));
 
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(list, 3, 2)]);
     });
 
     observeTest('removeRange changes length', () {
@@ -49,14 +49,14 @@
       list.removeRange(1, 3);
       expect(list, [1, 4]);
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(list, 3, 2)]);
     });
 
     observeTest('length= changes length', () {
       list.length = 5;
       expect(list, [1, 2, 3, null, null]);
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(list, 3, 5)]);
     });
 
     observeTest('[]= does not change length', () {
@@ -70,7 +70,7 @@
       list.clear();
       expect(list, []);
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(list, 3, 0)]);
     });
   });
 
@@ -82,7 +82,7 @@
       list = toObservable([1, 2, 3]);
       changes = null;
       sub = list.changes.listen((records) {
-        changes = records.where((r) => r.changes(1)).toList();
+        changes = getListChangeRecords(records, 1);
       });
     });
 
@@ -196,7 +196,7 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _lengthChange,
+        _lengthChange(list, 6, 8),
         _change(6, addedCount: 2)
       ]);
     });
@@ -215,7 +215,7 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _lengthChange,
+        _lengthChange(list, 6, 5),
         _change(5, removedCount: 1)
       ]);
     });
@@ -226,7 +226,7 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _lengthChange,
+        _lengthChange(list, 6, 3),
         _change(1, removedCount: 3),
       ]);
     });
@@ -247,14 +247,15 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _lengthChange,
+        _lengthChange(list, 6, 0),
         _change(0, removedCount: 6)
       ]);
     });
   });
 }
 
-final _lengthChange = new PropertyChangeRecord(#length);
+_lengthChange(list, int oldValue, int newValue) =>
+    new PropertyChangeRecord(list, #length, oldValue, newValue);
 
 _change(index, {removedCount: 0, addedCount: 0}) => new ListChangeRecord(
     index, removedCount: removedCount, addedCount: addedCount);
diff --git a/pkg/observe/test/observable_map_test.dart b/pkg/observe/test/observable_map_test.dart
index ce04f1b..c7ac0cf 100644
--- a/pkg/observe/test/observable_map_test.dart
+++ b/pkg/observe/test/observable_map_test.dart
@@ -27,7 +27,7 @@
       map = toObservable({'a': 1, 'b': 2, 'c': 3});
       changes = null;
       sub = map.changes.listen((records) {
-        changes = records.where((r) => r.changes(#length)).toList();
+        changes = getPropertyChangeRecords(records, #length);
       });
     });
 
@@ -37,14 +37,14 @@
       map['d'] = 4;
       expect(map, {'a': 1, 'b': 2, 'c': 3, 'd': 4});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(map, 3, 4)]);
     });
 
     observeTest('putIfAbsent changes length', () {
       map.putIfAbsent('d', () => 4);
       expect(map, {'a': 1, 'b': 2, 'c': 3, 'd': 4});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(map, 3, 4)]);
     });
 
     observeTest('remove changes length', () {
@@ -52,7 +52,10 @@
       map.remove('a');
       expect(map, {'b': 2});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange, _lengthChange]);
+      expectChanges(changes, [
+        _lengthChange(map, 3, 2),
+        _lengthChange(map, 2, 1)
+      ]);
     });
 
     observeTest('remove non-existent item does not change length', () {
@@ -73,7 +76,7 @@
       map.clear();
       expect(map, {});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_lengthChange]);
+      expectChanges(changes, [_lengthChange(map, 3, 0)]);
     });
   });
 
@@ -86,7 +89,8 @@
       map = toObservable({'a': 1, 'b': 2, 'c': 3});
       changes = null;
       sub = map.changes.listen((records) {
-        changes = records.where((r) => r.changes('b')).toList();
+        changes = records.where((r) => r is MapChangeRecord && r.key == 'b')
+            .toList();
       });
     });
 
@@ -103,14 +107,14 @@
       map['b'] = null;
       expect(map, {'a': 1, 'b': null, 'c': 3});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_change('b')]);
+      expectChanges(changes, [_changeKey('b', 2, null)]);
     });
 
     observeTest('set item to value', () {
       map['b'] = 777;
       expect(map, {'a': 1, 'b': 777, 'c': 3});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_change('b')]);
+      expectChanges(changes, [_changeKey('b', 2, 777)]);
     });
 
     observeTest('putIfAbsent does not change if already there', () {
@@ -132,7 +136,10 @@
       map['b'] = 42;
       expect(map, {'a': 1, 'b': 42, 'c': 3});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_change('b'), _change('b')]);
+      expectChanges(changes, [
+        _changeKey('b', 2, 9001),
+        _changeKey('b', 9001, 42)
+      ]);
     });
 
     observeTest('remove other items', () {
@@ -146,7 +153,7 @@
       map.remove('b');
       expect(map, {'a': 1, 'c': 3});
       performMicrotaskCheckpoint();
-      expectChanges(changes, [_change('b', isRemove: true)]);
+      expectChanges(changes, [_removeKey('b', 2)]);
     });
 
     observeTest('remove and add back', () {
@@ -155,7 +162,7 @@
       expect(map, {'a': 1, 'b': 2, 'c': 3});
       performMicrotaskCheckpoint();
       expectChanges(changes,
-          [_change('b', isRemove: true), _change('b', isInsert: true)]);
+          [_removeKey('b', 2), _insertKey('b', 2)]);
     });
   });
 
@@ -206,8 +213,8 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _lengthChange,
-        _change('c', isInsert: true),
+        _lengthChange(map, 2, 3),
+        _insertKey('c', 3),
       ]);
     });
 
@@ -220,9 +227,9 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _change('a'),
-        _lengthChange,
-        _change('c', isInsert: true)
+        _changeKey('a', 1, 42),
+        _lengthChange(map, 2, 3),
+        _insertKey('c', 3)
       ]);
     });
 
@@ -232,8 +239,8 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _change('b', isRemove: true),
-        _lengthChange,
+        _removeKey('b', 2),
+        _lengthChange(map, 2, 1),
       ]);
     });
 
@@ -243,15 +250,19 @@
 
       performMicrotaskCheckpoint();
       expectChanges(records, [
-        _change('a', isRemove: true),
-        _change('b', isRemove: true),
-        _lengthChange,
+        _removeKey('a', 1),
+        _removeKey('b', 2),
+        _lengthChange(map, 2, 0),
       ]);
     });
   });
 }
 
-final _lengthChange = new PropertyChangeRecord(#length);
+_lengthChange(map, int oldValue, int newValue) =>
+    new PropertyChangeRecord(map, #length, oldValue, newValue);
 
-_change(key, {isInsert: false, isRemove: false}) =>
-    new MapChangeRecord(key, isInsert: isInsert, isRemove: isRemove);
+_changeKey(key, old, newValue) => new MapChangeRecord(key, old, newValue);
+
+_insertKey(key, newValue) => new MapChangeRecord.insert(key, newValue);
+
+_removeKey(key, oldValue) => new MapChangeRecord.remove(key, oldValue);
diff --git a/pkg/observe/test/observe_test.dart b/pkg/observe/test/observe_test.dart
index 3415ccb..691634b 100644
--- a/pkg/observe/test/observe_test.dart
+++ b/pkg/observe/test/observe_test.dart
@@ -61,7 +61,7 @@
 }
 
 void _observeTests(createModel(x)) {
-  final watch = createModel(null) is! ChangeNotifierMixin;
+  final watch = createModel(null) is! ChangeNotifier;
 
   // Track the subscriptions so we can clean them up in tearDown.
   List subs;
@@ -109,7 +109,7 @@
 
     subs.add(t.changes.listen(expectAsync1((records) {
       called++;
-      expectChanges(records, _changedValue(watch ? 1 : 2));
+      expectPropertyChanges(records, watch ? 1 : 2);
     })));
 
     t.value = 41;
@@ -123,7 +123,7 @@
 
     subs.add(t.changes.listen(expectAsync1((records) {
       called++;
-      expectChanges(records, _changedValue(1));
+      expectPropertyChanges(records, 1);
       if (called == 1) {
         // Cause another change
         t.value = 777;
@@ -137,7 +137,7 @@
     var t = createModel(123);
 
     verifyRecords(records) {
-      expectChanges(records, _changedValue(watch ? 1 : 2));
+      expectPropertyChanges(records, watch ? 1 : 2);
     };
 
     subs.add(t.changes.listen(expectAsync1(verifyRecords)));
@@ -156,25 +156,25 @@
     expectChanges(records, [], reason: 'changes delived async');
 
     performMicrotaskCheckpoint();
-    expectChanges(records, _changedValue(watch ? 1 : 2));
+    expectPropertyChanges(records, watch ? 1 : 2);
     records.clear();
 
     t.value = 777;
     expectChanges(records, [], reason: 'changes delived async');
 
     performMicrotaskCheckpoint();
-    expectChanges(records, _changedValue(1));
+    expectPropertyChanges(records, 1);
 
     // Has no effect if there are no changes
     performMicrotaskCheckpoint();
-    expectChanges(records, _changedValue(1));
+    expectPropertyChanges(records, 1);
   });
 
   observeTest('cancel listening', () {
     var t = createModel(123);
     var sub;
     sub = t.changes.listen(expectAsync1((records) {
-      expectChanges(records, _changedValue(1));
+      expectPropertyChanges(records, 1);
       sub.cancel();
       t.value = 777;
       scheduleMicrotask(Observable.dirtyCheck);
@@ -186,12 +186,12 @@
     var t = createModel(123);
     var sub;
     sub = t.changes.listen(expectAsync1((records) {
-      expectChanges(records, _changedValue(1));
+      expectPropertyChanges(records, 1);
       sub.cancel();
 
       scheduleMicrotask(expectAsync0(() {
         subs.add(t.changes.listen(expectAsync1((records) {
-          expectChanges(records, _changedValue(1));
+          expectPropertyChanges(records, 1);
         })));
         t.value = 777;
         scheduleMicrotask(Observable.dirtyCheck);
@@ -207,12 +207,12 @@
     t.value = 42;
 
     performMicrotaskCheckpoint();
-    expectChanges(records, _changedValue(1));
+    expectPropertyChanges(records, 1);
 
     // Verify that mutation operations on the list fail:
 
     expect(() {
-      records[0] = new PropertyChangeRecord(#value);
+      records[0] = new PropertyChangeRecord(t, #value, 0, 1);
     }, throwsUnsupportedError);
 
     expect(() { records.clear(); }, throwsUnsupportedError);
@@ -224,10 +224,10 @@
     var t = createModel(123);
     var records = [];
     subs.add(t.changes.listen((r) { records.addAll(r); }));
-    t.notifyChange(new PropertyChangeRecord(#value));
+    t.notifyChange(new PropertyChangeRecord(t, #value, 123, 42));
 
     performMicrotaskCheckpoint();
-    expectChanges(records, _changedValue(1));
+    expectPropertyChanges(records, 1);
     expect(t.value, 123, reason: 'value did not actually change.');
   });
 
@@ -239,15 +239,23 @@
         reason: 'notifyPropertyChange returns newValue');
 
     performMicrotaskCheckpoint();
-    expectChanges(records, _changedValue(1));
+    expectPropertyChanges(records, 1);
     expect(t.value, 123, reason: 'value did not actually change.');
   });
 }
 
-_changedValue(len) => new List.filled(len, new PropertyChangeRecord(#value));
+expectPropertyChanges(records, int number) {
+  expect(records.length, number, reason: 'expected $number change records');
+  for (var record in records) {
+    expect(record is PropertyChangeRecord, true, reason:
+        'record should be PropertyChangeRecord');
+    expect((record as PropertyChangeRecord).name, #value, reason:
+        'record should indicate a change to the "value" property');
+  }
+}
 
 // A test model based on dirty checking.
-class WatcherModel<T> extends ObservableBase {
+class WatcherModel<T> extends Observable {
   @observable T value;
 
   WatcherModel([T initialValue]) : value = initialValue;
diff --git a/pkg/observe/test/observe_test_utils.dart b/pkg/observe/test/observe_test_utils.dart
index 2937c07..2025e1b 100644
--- a/pkg/observe/test/observe_test_utils.dart
+++ b/pkg/observe/test/observe_test_utils.dart
@@ -4,6 +4,8 @@
 
 library observe.test.observe_test_utils;
 
+import 'package:observe/observe.dart';
+
 import 'package:unittest/unittest.dart';
 
 import 'package:observe/src/microtask.dart';
@@ -14,6 +16,12 @@
 expectChanges(actual, expected, {reason}) =>
     expect('$actual', '$expected', reason: reason);
 
+List getListChangeRecords(List changes, int index) => changes
+    .where((c) => c is ListChangeRecord && c.indexChanged(index)).toList();
+
+List getPropertyChangeRecords(List changes, Symbol property) => changes
+    .where((c) => c is PropertyChangeRecord && c.name == property).toList();
+
 /**
  * This is a special kind of unit [test], that supports
  * calling [performMicrotaskCheckpoint] during the test to pump events
diff --git a/pkg/observe/test/path_observer_test.dart b/pkg/observe/test/path_observer_test.dart
index f2aff93..c620204 100644
--- a/pkg/observe/test/path_observer_test.dart
+++ b/pkg/observe/test/path_observer_test.dart
@@ -15,15 +15,6 @@
 
 observePath(obj, path) => new PathObserver(obj, path);
 
-toSymbolMap(Map map) {
-  var result = new ObservableMap.linked();
-  map.forEach((key, value) {
-    if (value is Map) value = toSymbolMap(value);
-    result[new Symbol(key)] = value;
-  });
-  return result;
-}
-
 observePathTests() {
   observeTest('Degenerate Values', () {
     expect(observePath(null, '').value, null);
@@ -66,45 +57,45 @@
 
 
   observeTest('get value at path ObservableMap', () {
-    var obj = toSymbolMap({'a': {'b': {'c': 1}}});
+    var obj = toObservable({'a': {'b': {'c': 1}}});
 
     expect(observePath(obj, '').value, obj);
-    expect(observePath(obj, 'a').value, obj[#a]);
-    expect(observePath(obj, 'a.b').value, obj[#a][#b]);
+    expect(observePath(obj, 'a').value, obj['a']);
+    expect(observePath(obj, 'a.b').value, obj['a']['b']);
     expect(observePath(obj, 'a.b.c').value, 1);
 
-    obj[#a][#b][#c] = 2;
+    obj['a']['b']['c'] = 2;
     expect(observePath(obj, 'a.b.c').value, 2);
 
-    obj[#a][#b] = toSymbolMap({'c': 3});
+    obj['a']['b'] = toObservable({'c': 3});
     expect(observePath(obj, 'a.b.c').value, 3);
 
-    obj[#a] = toSymbolMap({'b': 4});
+    obj['a'] = toObservable({'b': 4});
     expect(observePath(obj, 'a.b.c').value, null);
     expect(observePath(obj, 'a.b').value, 4);
   });
 
   observeTest('set value at path', () {
-    var obj = toSymbolMap({});
+    var obj = toObservable({});
     observePath(obj, 'foo').value = 3;
-    expect(obj[#foo], 3);
+    expect(obj['foo'], 3);
 
-    var bar = toSymbolMap({ 'baz': 3 });
+    var bar = toObservable({ 'baz': 3 });
     observePath(obj, 'bar').value = bar;
-    expect(obj[#bar], bar);
+    expect(obj['bar'], bar);
 
     observePath(obj, 'bar.baz.bat').value = 'not here';
     expect(observePath(obj, 'bar.baz.bat').value, null);
   });
 
   observeTest('set value back to same', () {
-    var obj = toSymbolMap({});
+    var obj = toObservable({});
     var path = observePath(obj, 'foo');
     var values = [];
     path.changes.listen((_) { values.add(path.value); });
 
     path.value = 3;
-    expect(obj[#foo], 3);
+    expect(obj['foo'], 3);
     expect(path.value, 3);
 
     observePath(obj, 'foo').value = 2;
@@ -121,16 +112,16 @@
   });
 
   observeTest('Observe and Unobserve - Paths', () {
-    var arr = toSymbolMap({});
+    var arr = toObservable({});
 
-    arr[#foo] = 'bar';
+    arr['foo'] = 'bar';
     var fooValues = [];
     var fooPath = observePath(arr, 'foo');
     var fooSub = fooPath.changes.listen((_) {
       fooValues.add(fooPath.value);
     });
-    arr[#foo] = 'baz';
-    arr[#bat] = 'bag';
+    arr['foo'] = 'baz';
+    arr['bat'] = 'bag';
     var batValues = [];
     var batPath = observePath(arr, 'bat');
     var batSub = batPath.changes.listen((_) {
@@ -141,11 +132,11 @@
     expect(fooValues, ['baz']);
     expect(batValues, []);
 
-    arr[#foo] = 'bar';
+    arr['foo'] = 'bar';
     fooSub.cancel();
-    arr[#bat] = 'boo';
+    arr['bat'] = 'boo';
     batSub.cancel();
-    arr[#bat] = 'boot';
+    arr['bat'] = 'boot';
 
     performMicrotaskCheckpoint();
     expect(fooValues, ['baz']);
@@ -206,26 +197,26 @@
   }
 
   observeTest('observe map', () {
-    var model = toSymbolMap({'a': 1});
+    var model = toObservable({'a': 1});
     var path = observePath(model, 'a');
 
     var values = [path.value];
     var sub = path.changes.listen((_) { values.add(path.value); });
     expect(values, [1]);
 
-    model[#a] = 2;
+    model['a'] = 2;
     performMicrotaskCheckpoint();
     expect(values, [1, 2]);
 
     sub.cancel();
-    model[#a] = 3;
+    model['a'] = 3;
     performMicrotaskCheckpoint();
     expect(values, [1, 2]);
   });
 }
 
 @reflectable
-class TestModel extends ChangeNotifierBase {
+class TestModel extends ChangeNotifier {
   var _a, _b, _c;
 
   TestModel();
@@ -249,7 +240,7 @@
   }
 }
 
-class WatcherModel extends ObservableBase {
+class WatcherModel extends Observable {
   // TODO(jmesserly): dart2js does not let these be on the same line:
   // @observable var a, b, c;
   @observable var a;
diff --git a/pkg/observe/test/transform_test.dart b/pkg/observe/test/transform_test.dart
index 997ef8d..73720cc 100644
--- a/pkg/observe/test/transform_test.dart
+++ b/pkg/observe/test/transform_test.dart
@@ -12,28 +12,28 @@
   useCompactVMConfiguration();
 
   group('replaces Observable for ChangeNotifier', () {
-    _testClause('extends ObservableBase', 'extends ChangeNotifierBase');
-    _testClause('extends Base with ObservableMixin',
-        'extends Base with ChangeNotifierMixin');
-    _testClause('extends Base<T> with ObservableMixin',
-        'extends Base<T> with ChangeNotifierMixin');
-    _testClause('extends Base with Mixin, ObservableMixin',
-        'extends Base with Mixin, ChangeNotifierMixin');
-    _testClause('extends Base with ObservableMixin, Mixin',
-        'extends Base with ChangeNotifierMixin, Mixin');
-    _testClause('extends Base with Mixin<T>, ObservableMixin',
-        'extends Base with Mixin<T>, ChangeNotifierMixin');
-    _testClause('extends Base with Mixin, ObservableMixin, Mixin2',
-        'extends Base with Mixin, ChangeNotifierMixin, Mixin2');
-    _testClause('extends ObservableBase implements Interface',
-        'extends ChangeNotifierBase implements Interface');
-    _testClause('extends ObservableBase implements Interface<T>',
-        'extends ChangeNotifierBase implements Interface<T>');
-    _testClause('extends Base with ObservableMixin implements Interface',
-        'extends Base with ChangeNotifierMixin implements Interface');
+    _testClause('extends Observable', 'extends ChangeNotifier');
+    _testClause('extends Base with Observable',
+        'extends Base with ChangeNotifier');
+    _testClause('extends Base<T> with Observable',
+        'extends Base<T> with ChangeNotifier');
+    _testClause('extends Base with Mixin, Observable',
+        'extends Base with Mixin, ChangeNotifier');
+    _testClause('extends Base with Observable, Mixin',
+        'extends Base with ChangeNotifier, Mixin');
+    _testClause('extends Base with Mixin<T>, Observable',
+        'extends Base with Mixin<T>, ChangeNotifier');
+    _testClause('extends Base with Mixin, Observable, Mixin2',
+        'extends Base with Mixin, ChangeNotifier, Mixin2');
+    _testClause('extends Observable implements Interface',
+        'extends ChangeNotifier implements Interface');
+    _testClause('extends Observable implements Interface<T>',
+        'extends ChangeNotifier implements Interface<T>');
+    _testClause('extends Base with Observable implements Interface',
+        'extends Base with ChangeNotifier implements Interface');
     _testClause(
-        'extends Base with Mixin, ObservableMixin implements I1, I2',
-        'extends Base with Mixin, ChangeNotifierMixin implements I1, I2');
+        'extends Base with Mixin, Observable implements I1, I2',
+        'extends Base with Mixin, ChangeNotifier implements I1, I2');
   });
 
   group('fixes contructor calls ', () {
@@ -150,7 +150,7 @@
 library A_foo;
 import 'package:observe/observe.dart';
 
-class A extends ObservableBase {
+class A extends Observable {
   @$annotation int foo;
   A(this.foo);
 }
@@ -159,7 +159,7 @@
 String _sampleObservableOutput(String annotation) =>
     "library A_foo;\n"
     "import 'package:observe/observe.dart';\n\n"
-    "class A extends ChangeNotifierBase {\n"
+    "class A extends ChangeNotifier {\n"
     "  @reflectable @$annotation int get foo => __\$foo; int __\$foo; "
       "${_makeSetter('int', 'foo')}\n"
     "  A(foo) : __\$foo = foo;\n"
@@ -169,7 +169,7 @@
     '__\$$name = notifyPropertyChange(#$name, __\$$name, value); }';
 
 String _complexObservable(String annotation) => '''
-class Foo extends ObservableBase {
+class Foo extends Observable {
   @$annotation
   @otherMetadata
       Foo
@@ -181,7 +181,7 @@
 ''';
 
 String _complexObservableOutput(String meta) =>
-    "class Foo extends ChangeNotifierBase {\n"
+    "class Foo extends ChangeNotifier {\n"
     "  @reflectable @$meta\n"
     "  @otherMetadata\n"
     "      Foo\n"
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 4ccd559..c5c8bf6 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -13,10 +13,12 @@
 # Skip non-test files ending with "_test".
 scheduled_test/lib/*: Skip
 polymer/example/scoped_style/*: Skip
+polymer/test/instance_attrs_test: Pass, Slow, Fail # Issue 14248
 
 scheduled_test/test/scheduled_server_test: Pass, Slow, Fail # Issue 9231, 13524
 scheduled_test/test/scheduled_process_test: Pass, Slow # Issue 9231
 
+
 # Skip test not runnable via test.dart
 third_party/html5lib/test/dom_compat_test: Skip
 third_party/html5lib/test/browser/browser_test: Skip
@@ -36,6 +38,18 @@
 sequence_zip/test/stream_test: RuntimeError, OK # Timers are not supported.
 unittest/test/missing_tick_test: Fail # Timer interface not supported: dartbug.com/7728.
 
+[ $runtime == vm || $runtime == d8 || $runtime == jsshell ]
+polymer/example: Skip # Uses dart:html
+polymer/test/attr_deserialize_test: Skip # uses dart:html
+polymer/test/attr_mustache_test: Skip #uses dart:html
+polymer/test/event_path_test: Skip #uses dart:html
+polymer/test/events_test: Skip #uses dart:html
+polymer/test/instance_attrs_test: Skip #uses dart:html
+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/take_attributes_test: Skip #uses dart:html
+
 [$compiler == dart2dart]
 *: Skip
 
@@ -51,6 +65,14 @@
 [ $runtime == ie9 ]
 intl/test/date_time_format_http_request_test: Fail # Issue 8983
 mime/test/mime_multipart_transformer_test: Skip # No typed_data on IE9.
+polymer/test/instance_attrs_test: Pass, Fail # Issue 14167
+
+[ $system == windows && $runtime == ff ]
+polymer/test/events_test: Pass, Fail # Issue 14167
+polymer/test/prop_attr_bind_reflection_test: Pass, Fail # Issue 14167
+polymer/test/prop_attr_reflection_test: Pass, Fail # Issue 14167
+polymer/test/take_attributes_test: Pass, Fail # Issue 14167
+polymer/test/attr_mustache_test: Pass, Fail # Issue 14167
 
 [ $runtime == safari ]
 fixnum/test/int_64_test: Pass, Fail # Bug in JSC.
@@ -88,16 +110,6 @@
 path/test/browser_test: Fail, OK # Uses dart:html
 intl/test/find_default_locale_browser_test: Skip
 intl/test/date_time_format_http_request_test: Skip
-polymer/test/attr_deserialize_test: Fail, OK # Uses dart:html
-polymer/test/attr_mustache_test: Fail, OK # Uses dart:html
-polymer/test/event_path_test: Fail, OK # Uses dart:html
-polymer/test/events_test: Fail, OK # Uses dart:html
-polymer/test/instance_attrs_test: Fail, OK # Uses dart:html
-polymer/test/prop_attr_reflection_test: Fail, OK # Uses dart:html
-polymer/test/prop_attr_bind_reflection_test: Fail, OK # Uses dart:html
-polymer/test/publish_attributes_test: Fail, OK # Uses dart:html
-polymer/test/take_attributes_test: Fail, OK # Uses dart:html
-polymer/example: Fail, OK # Uses dart:html
 
 [ $runtime == vm && $system == windows ]
 docgen/test/single_library_test: Fail # Issue 11985
@@ -210,10 +222,9 @@
 *: Skip  # Issue 13624
 
 [ $arch == simarm || $arch == simmips ]
-barback/test/too_many_open_files_test: Pass, Slow
+barback/test/too_many_open_files_test: Pass, Slow, Fail # 14220
 third_party/html5lib/test/tokenizer_test: Pass, Slow
 watcher/test/no_subscription_test: Pass, Fail  # Issue 13705.
-barback/test/too_many_open_files_test: Pass, Slow
 
 # Skip serialization test that explicitly has no library declaration in the
 # test on Dartium, which requires all tests to have a library.
@@ -281,5 +292,14 @@
 # pkg issue 13945; Missing inherited member 'Trace.frames'
 observe/test/observe_test: fail
 
+[ $compiler == dart2analyzer ]
+# pkg issue 13944; Missing inherited members: 'ListChangeRecord.addedCount' and 'ListChangeRecord.removedCount'
+custom_element/test/analyzer_test: fail
+mdv/test/analyzer_test: fail
+observe/test/observe_test: fail
+
+# pkg issue 13945; Missing inherited member 'Trace.frames'
+observe/test/observe_test: fail
+
 [ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]
 polymer/test/prop_attr_reflection_test: fail # Issue 14036
diff --git a/pkg/polymer/example/component/news/test/news_index_test.dart b/pkg/polymer/example/component/news/test/news_index_test.dart
index ed804cd..e705c99 100644
--- a/pkg/polymer/example/component/news/test/news_index_test.dart
+++ b/pkg/polymer/example/component/news/test/news_index_test.dart
@@ -10,7 +10,7 @@
 /**
  * This test runs the news example and checks the state of the initial page.
  */
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   extractLinks(nodes) => nodes.where((n) => n is Element)
diff --git a/pkg/polymer/example/component/news/test/news_index_test.html b/pkg/polymer/example/component/news/test/news_index_test.html
index 873b2d5..8e5dbfd 100644
--- a/pkg/polymer/example/component/news/test/news_index_test.html
+++ b/pkg/polymer/example/component/news/test/news_index_test.html
@@ -7,7 +7,6 @@
 <head>
   <title>Simple Web Components Example</title>
   <link rel="import" href="../web/news-component.html">
-  <script src="packages/polymer/boot.js"></script>
   <script src="packages/unittest/test_controller.js"></script>
 </head>
 <body>
@@ -21,5 +20,6 @@
     <li class="breaking"><a href="//example.com/stories/5">Horrible story</a></li>
 </ul>
 <script type="application/dart" src="news_index_test.dart"></script>
+<script type="application/dart" src="packages/polymer/init.dart"></script>
 </body>
 </html>
diff --git a/pkg/polymer/example/component/news/web/index.html b/pkg/polymer/example/component/news/web/index.html
index 3354d9b..f6e7ce0 100644
--- a/pkg/polymer/example/component/news/web/index.html
+++ b/pkg/polymer/example/component/news/web/index.html
@@ -7,7 +7,6 @@
 <head>
     <title>Simple Web Components Example</title>
     <link rel="import" href="news-component.html">
-    <script src='packages/polymer/boot.js'></script>
 </head>
 <body>
 <h1>Simple Web Components Example</h1>
@@ -19,6 +18,7 @@
     <li><a href="//example.com/stories/4">Awesome story</a></li>
     <li class="breaking"><a href="//example.com/stories/5">Horrible story</a></li>
 </ul>
-  <script type="application/dart">main() {}</script>
+  <script type="application/dart" src="packages/polymer/init.dart"></script>
+  <script src='packages/browser/dart.js'></script>
 </body>
 </html>
diff --git a/pkg/polymer/lib/boot.js b/pkg/polymer/lib/boot.js
index c273569..d46090f 100644
--- a/pkg/polymer/lib/boot.js
+++ b/pkg/polymer/lib/boot.js
@@ -2,208 +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.
 
-// This script dynamically prepares a set of files to run polymer.dart. It uses
-// the html_import polyfill to search for all imported files, then
-// it inlines all <polymer-element> definitions on the top-level page (needed by
-// registerPolymerElement), and it removes script tags that appear inside
-// those tags. It finally rewrites the main entrypoint to call an initialization
-// function on each of the declared <polymer-elements>.
-//
-// This script is needed only when running polymer.dart in Dartium. It should be
-// removed by the polymer deployment commands.
-
-// As an example, given an input of this form:
-//   <polymer-element name="c1">
-//      <template></template>
-//      <script type="application/dart" src="url0.dart"></script>
-//   </polymer-element>
-//   <element name="c2">
-//      <template></template>
-//      <script type="application/dart">main() => { print('body2'); }</script>
-//   </element>
-//   <c1></c1>
-//   <c2></c2>
-//   <script type="application/dart" src="url2.dart"></script>
-//   <script src="packages/polymer/boot.js"></script>
-//
-// This script will simplifies the page as follows:
-//   <polymer-element name="c1">
-//      <template></template>
-//   </polymer-element>
-//   <polymer-element name="c2">
-//      <template></template>
-//   </polymer-element>
-//   <c1></c1>
-//   <c2></c2>
-//   <script type="application/dart">
-//     import 'url0.dart' as i0;
-//     import "data:application/dart;base64,CiAgICBtYWluKCkgewogICAgICBwcmludCgnYm9keTInKTsKICAgIH0KICAgIA==" as i1;
-//     import 'url2.dart' as i2;
-//     ...
-//     main() {
-//       // code that checks which libraries have a 'main' and invokes them.
-//       // practically equivalent to: i0._init(); i1._init(); i2.main();
-//     }
-//   </script>
-
-
 (function() {
-  // Only run in Dartium.
-  if (!navigator.webkitStartDart) {
-    // TODO(sigmund): rephrase when we split build.dart in two: analysis vs
-    // deploy pieces.
-    console.warn('boot.js only works in Dartium. Run the build.dart' +
-      ' tool to compile a deployable JavaScript version')
-    return;
-  }
-
-  // Detect if dart.js was included in the page. We use DOMContentLoaded to make
-  // sure we also check for occurrences after the current tag.
-  window.addEventListener('DOMContentLoaded', function () {
-    var dartJSQuery = 'script[src="packages/browser/dart.js"]';
-    if (!!document.querySelector(dartJSQuery)) {
-      console.error('Error: found "packages/browser/dart.js" in the ' +
-        'page. Please remove it. When using polymer\'s "boot.js", ' +
-        'you can\'t use "dart.js".');
-    }
-  });
-
-  // Load HTML Imports:
-  var htmlImportsSrc = 'src="packages/html_import/html_import.min.js"';
-  var htmlImportsTag = '<script ' + htmlImportsSrc + '></script>';
-  var importScript = document.querySelector('script[' + htmlImportsSrc + ']');
-
-  if (!importScript) {
-    try {
-      document.write(htmlImportsTag);
-      importScript = document.querySelector('script[' + htmlImportsSrc + ']');
-    } catch (e) {
-      console.error(
-        "Failed to use document.write() to inject the HTML import " +
-        "polyfill.\nIf you are running with Content Security Policy, " +
-        "try adding the following to your HTML's <head> BEFORE the " +
-        "line that includes polymer/boot.js:\n    " + htmlImportsTag);
-      return;
-    }
-  }
-
-  importScript.addEventListener('load', function() {
-    // NOTE: this is from polymer/src/lib/dom.js
-    window.HTMLImports.importer.preloadSelectors +=
-        ', polymer-element link[rel=stylesheet]';
-  });
-
-  // TODO(jmesserly): we need this in deploy tool too.
-  // NOTE: this is from polymer/src/boot.js:
-  // FOUC prevention tactic
-  var style = document.createElement('style');
-  style.textContent = 'body {opacity: 0;}';
-  var head = document.querySelector('head');
-  head.insertBefore(style, head.firstChild);
-
-  window.addEventListener('WebComponentsReady', function() {
-    document.body.style.webkitTransition = 'opacity 0.3s';
-    document.body.style.opacity = 1;
-  });
-
-  // Extract a Dart import URL from a script tag, which is the 'src' attribute
-  // of the script tag, or a data-url with the script contents for inlined code.
-  function getScriptUrl(script) {
-    var url = script.src;
-    if (url) {
-      // Normalize package: urls
-      var index = url.indexOf('packages/');
-      if (index == 0 || (index > 0 && url[index - 1] == '/')) {
-        url = "package:" + url.slice(index + 9);
-      }
-      return url;
-    } else {
-      // TODO(sigmund): investigate how to eliminate the warning in Dartium
-      // (changing to text/javascript hides the warning, but seems wrong).
-      return "data:application/dart;base64," + window.btoa(script.textContent);
-    }
-  }
-
-  // Moves <polymer-elements> from imported documents into the top-level page.
-  function inlinePolymerElements(content, ref, seen) {
-    if (!seen) seen = {};
-    var links = content.querySelectorAll('link[rel="import"]');
-    for (var i = 0; i < links.length; i++) {
-      var link = links[i];
-      // TODO(jmesserly): figure out why ".import" fails in content_shell but
-      // works in Dartium.
-      if (link.import && link.import.href) link = link.import;
-
-      if (seen[link.href]) continue;
-      seen[link.href] = link;
-      inlinePolymerElements(link.content, ref, seen);
-    }
-
-    if (content != document) { // no need to do anything for the top-level page
-      var elements = content.querySelectorAll('polymer-element');
-      for (var i = 0; i < elements.length; i++)  {
-        document.body.insertBefore(elements[i], ref);
-      }
-    }
-  }
-
-  // Creates a Dart program that imports [urls] and passes them to initPolymer
-  // (which in turn will invoke their main function, their methods marked with
-  // @initMethod, and register any custom tag labeled with @CustomTag).
-  function createMain(urls, mainUrl) {
-    var imports = Array(urls.length + 1);
-    for (var i = 0; i < urls.length; ++i) {
-      imports[i] = 'import "' + urls[i] + '" as i' + i + ';';
-    }
-    imports[urls.length] = 'import "package:polymer/polymer.dart" as polymer;';
-    var arg = urls.length == 0 ? '[]' :
-        ('[\n      "' + urls.join('",\n      "') + '"\n     ]');
-    return (imports.join('\n') +
-        '\n\nmain() {\n' +
-        '  polymer.initPolymer(' + arg + ');\n' +
-        '}\n');
-  }
-
-  // Finds all top-level <script> tags, and <script> tags in custom elements
-  // and merges them into a single entrypoint.
-  function mergeScripts() {
-    var scripts = document.getElementsByTagName("script");
-    var length = scripts.length;
-
-    var urls = [];
-    var toRemove = [];
-
-    // Collect the information we need to replace the script tags
-    for (var i = 0; i < length; ++i) {
-      var script = scripts[i];
-      if (script.type == "application/dart") {
-        urls.push(getScriptUrl(script));
-        toRemove.push(script);
-      }
-    }
-
-    toRemove.forEach(function (s) { s.parentNode.removeChild(s); });
-
-    // Append a new script tag that initializes everything.
-    var newScript = document.createElement('script');
-    newScript.type = "application/dart";
-    newScript.textContent = createMain(urls);
-    document.body.appendChild(newScript);
-  }
-
-  var alreadyRan = false;
-  window.addEventListener('HTMLImportsLoaded', function (e) {
-    if (alreadyRan) {
-      console.warn('HTMLImportsLoaded fired again.');
-      return;
-    }
-    alreadyRan = true;
-    var ref = document.body.children[0];
-    inlinePolymerElements(document, ref);
-    mergeScripts();
-    if (!navigator.webkitStartDart()) {
-      document.body.innerHTML = 'This build has expired. Please download a ' +
-          'new Dartium at http://www.dartlang.org/dartium/index.html';
-    }
-  });
+  console.error('"boot.js" is now deprecated. Instead, you can initialize '
+    + 'your polymer application by adding the following tags: \'' +
+    + '<script type="application/dart" src="packages/polymer/init.dart">'
+    + '</script><script src="packages/browser/dart.js"></script>\'. '
+    + 'Make sure these script tags come after all HTML imports.');
 })();
diff --git a/pkg/polymer/lib/init.dart b/pkg/polymer/lib/init.dart
new file mode 100644
index 0000000..8ca18c1
--- /dev/null
+++ b/pkg/polymer/lib/init.dart
@@ -0,0 +1,23 @@
+// 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 that automatically initializes polymer elements without having to
+ * write a main for your application.
+ *
+ * If a polymer application is written entirely with `<polymer-element>` tags
+ * and there is no initialization code that needs to happen before these
+ * elements are created, then, instead of creating your own `main`, you can
+ * simply include a script tag loading this library:
+ *
+ *    <script type="application/dart" src="packages/polymer/init.dart">
+ *    </script>
+ *
+ * This script tag should be placed after all HTML imports on your page.
+ */
+library polymer.init;
+
+import 'package:polymer/polymer.dart';
+
+main() => initPolymer();
diff --git a/pkg/polymer/lib/polymer.dart b/pkg/polymer/lib/polymer.dart
index ebd963a..62bec7c 100644
--- a/pkg/polymer/lib/polymer.dart
+++ b/pkg/polymer/lib/polymer.dart
@@ -68,6 +68,7 @@
 export 'package:observe/html.dart';
 export 'package:observe/src/microtask.dart';
 
+part 'src/boot.dart';
 part 'src/declaration.dart';
 part 'src/instance.dart';
 part 'src/loader.dart';
diff --git a/pkg/polymer/lib/src/boot.dart b/pkg/polymer/lib/src/boot.dart
new file mode 100644
index 0000000..8e8618f
--- /dev/null
+++ b/pkg/polymer/lib/src/boot.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/** Ported from `polymer/src/boot.js`. **/
+part of polymer;
+
+/** Prevent a flash of unstyled content. */
+preventFlashOfUnstyledContent() {
+  var style = new StyleElement();
+  style.text = r'body {opacity: 0;}';
+  // Note: we use `query` and not `document.head` to make sure this code works
+  // with the shadow_dom polyfill (a limitation of the polyfill is that it can't
+  // override the definitions of document, document.head, or document.body).
+  var head = query('head');
+  head.insertBefore(style, head.firstChild);
+
+  Polymer.onReady.then((_) {
+    document.body.style.transition = 'opacity 0.3s';
+    document.body.style.opacity = '1';
+  });
+}
diff --git a/pkg/polymer/lib/src/build/import_inliner.dart b/pkg/polymer/lib/src/build/import_inliner.dart
index 987fe9f..98924f0 100644
--- a/pkg/polymer/lib/src/build/import_inliner.dart
+++ b/pkg/polymer/lib/src/build/import_inliner.dart
@@ -13,13 +13,14 @@
 import 'package:html5lib/dom_parsing.dart' show TreeVisitor;
 import 'common.dart';
 
-/** Recursively inlines polymer-element definitions from html imports. */
-// TODO(sigmund): make sure we match semantics of html-imports for tags other
-// than polymer-element (see dartbug.com/12613).
-class ImportedElementInliner extends Transformer with PolymerTransformer {
+/** Recursively inlines the contents of HTML imports. */
+// TODO(sigmund): currently we just inline polymer-element and script tags, we
+// need to make sure we match semantics of html-imports for other tags too.
+// (see dartbug.com/12613).
+class ImportInliner extends Transformer with PolymerTransformer {
   final TransformOptions options;
 
-  ImportedElementInliner(this.options);
+  ImportInliner(this.options);
 
   /** Only run on entry point .html files. */
   Future<bool> isPrimary(Asset input) =>
@@ -53,9 +54,9 @@
   }
 
   /**
-   * Visits imports in [document] and add their polymer-element definitions to
-   * [elements], unless they have already been [seen]. Elements are added in the
-   * order they appear, transitive imports are added first.
+   * Visits imports in [document] and add their polymer-element and script tags
+   * to [elements], unless they have already been [seen]. Elements are added in
+   * the order they appear, transitive imports are added first.
    */
   Future<bool> _visitImports(Document document, AssetId sourceId,
       Transform transform, Set<AssetId> seen, List<Node> elements) {
@@ -66,7 +67,8 @@
       var href = tag.attributes['href'];
       var id = resolve(sourceId, href, transform.logger, tag.sourceSpan);
       hasImports = true;
-      if (id == null || seen.contains(id)) continue;
+      if (id == null || seen.contains(id) ||
+         (id.package == 'polymer' && id.path == 'lib/init.html')) continue;
       importIds.add(id);
     }
 
@@ -76,28 +78,40 @@
     return Future.forEach(importIds, (id) {
       if (seen.contains(id)) return new Future.value(null);
       seen.add(id);
-      return _collectPolymerElements(id, transform, seen, elements);
+      return _collectElements(id, transform, seen, elements);
     }).then((_) => true);
   }
 
   /**
    * Loads an asset identified by [id], visits its imports and collects it's
-   * polymer-element definitions.
+   * polymer-element definitions and script tags.
    */
-  Future _collectPolymerElements(AssetId id, Transform transform,
+  Future _collectElements(AssetId id, Transform transform,
       Set<AssetId> seen, List elements) {
     return readAsHtml(id, transform).then((document) {
       return _visitImports(document, id, transform, seen, elements).then((_) {
-        var normalizer = new _UrlNormalizer(transform, id);
-        for (var element in document.queryAll('polymer-element')) {
-          normalizer.visit(document);
-          elements.add(element);
-        }
+        new _UrlNormalizer(transform, id).visit(document);
+        new _InlineQuery(elements).visit(document);
       });
     });
   }
 }
 
+/** Implements document.queryAll('polymer-element,script'). */
+// TODO(sigmund): delete this (dartbug.com/14135)
+class _InlineQuery extends TreeVisitor {
+  final List<Element> elements;
+  _InlineQuery(this.elements);
+
+  visitElement(Element node) {
+    if (node.tagName == 'polymer-element' || node.tagName == 'script') {
+      elements.add(node);
+    } else {
+      super.visitElement(node);
+    }
+  }
+}
+
 /** Internally adjusts urls in the html that we are about to inline. */
 class _UrlNormalizer extends TreeVisitor {
   final Transform transform;
@@ -111,7 +125,7 @@
     for (var key in node.attributes.keys) {
       if (_urlAttributes.contains(key)) {
         var url = node.attributes[key];
-        if (url != null && url != '') {
+        if (url != null && url != '' && !url.startsWith('{{')) {
           node.attributes[key] = _newUrl(url, node.sourceSpan);
         }
       }
diff --git a/pkg/polymer/lib/src/build/linter.dart b/pkg/polymer/lib/src/build/linter.dart
index b6df83a..bf95215 100644
--- a/pkg/polymer/lib/src/build/linter.dart
+++ b/pkg/polymer/lib/src/build/linter.dart
@@ -47,7 +47,8 @@
     seen.add(id);
     return readPrimaryAsHtml(wrapper).then((document) {
       return _collectElements(document, id, wrapper, seen).then((elements) {
-        new _LinterVisitor(wrapper, elements).visit(document);
+        bool isEntrypoint = options.isHtmlEntryPoint(id);
+        new _LinterVisitor(wrapper, elements, isEntrypoint).run(document);
         var messagesId = id.addExtension('.messages');
         wrapper.addOutput(new Asset.fromString(messagesId,
             wrapper._messages.join('\n')));
@@ -90,7 +91,8 @@
       var href = tag.attributes['href'];
       var span = tag.sourceSpan;
       var id = resolve(sourceId, href, logger, span);
-      if (id == null) continue;
+      if (id == null ||
+          (id.package == 'polymer' && id.path == 'lib/init.html')) continue;
       importIds.add(assetExists(id, transform).then((exists) {
         if (exists) return id;
         if (sourceId == transform.primaryInput.id) {
@@ -218,9 +220,12 @@
 class _LinterVisitor extends TreeVisitor {
   TransformLogger _logger;
   bool _inPolymerElement = false;
+  bool _dartJSSeen = false;
+  bool _initSeen = false;
+  bool _isEntrypoint;
   Map<String, _ElementSummary> _elements;
 
-  _LinterVisitor(this._logger, this._elements) {
+  _LinterVisitor(this._logger, this._elements, this._isEntrypoint) {
     // We normalize the map, so each element has a direct reference to any
     // element it extends from.
     for (var tag in _elements.values) {
@@ -243,11 +248,30 @@
     }
   }
 
+  void run(Document doc) {
+    visit(doc);
+
+    if (_isEntrypoint && !_initSeen) {
+      _logger.error(USE_INIT_DART, span: doc.body.sourceSpan);
+    } 
+
+    if (_isEntrypoint && !_dartJSSeen) {
+      // TODO(sigmund): remove this when webkitStartDart is gone.
+      _logger.error(USE_DART_JS, span: doc.body.sourceSpan);
+    }
+  }
+
   /** Produce warnings for invalid link-rel tags. */
   void _validateLinkElement(Element node) {
     var rel = node.attributes['rel'];
     if (rel != 'import' && rel != 'stylesheet') return;
 
+    if (rel == 'import' && _initSeen) {
+      _logger.warning(
+          "Move HTML imports above the 'polymer/init.dart' script tag",
+          span: node.sourceSpan);
+    }
+
     var href = node.attributes['href'];
     if (href != null && href != '') return;
 
@@ -340,22 +364,40 @@
             'be treated as JavaScript. Did you forget type="application/dart"?',
             span: node.sourceSpan);
       }
+    }
+
+    if (src == null) return;
+
+    if (src == 'packages/polymer/boot.js') {
+      _logger.warning(BOOT_JS_DEPRECATED, span: node.sourceSpan);
+      return;
+    }
+    if (src == 'packages/browser/dart.js' ||
+        src == 'packages/unittest/test_controller.js') {
+      _dartJSSeen = true;
+      return;
+    }
+
+    if (src == 'packages/polymer/init.dart') {
+      _initSeen = true;
+      if (scriptType != 'application/dart') {
+        _logger.warning('wrong script type, expected type="application/dart".',
+            span: node.sourceSpan);
+      }
       return;
     }
 
     if (scriptType != 'application/dart') return;
 
-    if (src != null) {
-      if (!src.endsWith('.dart')) {
-        _logger.warning('"application/dart" scripts should '
-            'use the .dart file extension.',
-            span: node.sourceSpan);
-      }
+    if (!src.endsWith('.dart')) {
+      _logger.warning('"application/dart" scripts should '
+          'use the .dart file extension.',
+          span: node.sourceSpan);
+    }
 
-      if (node.innerHtml.trim() != '') {
-        _logger.warning('script tag has "src" attribute and also has script '
-            'text.', span: node.sourceSpan);
-      }
+    if (node.innerHtml.trim() != '') {
+      _logger.warning('script tag has "src" attribute and also has script '
+          'text.', span: node.sourceSpan);
     }
   }
 
@@ -497,6 +539,24 @@
   return !_invalidTagNames.containsKey(name);
 }
 
-final String _RED_COLOR = '\u001b[31m';
-final String _MAGENTA_COLOR = '\u001b[35m';
-final String _NO_COLOR = '\u001b[0m';
+const String _RED_COLOR = '\u001b[31m';
+const String _MAGENTA_COLOR = '\u001b[35m';
+const String _NO_COLOR = '\u001b[0m';
+
+const String USE_INIT_DART = 
+    'To run a polymer applications, make sure to include '
+    '\'<script type="application/dart" src="packages/polymer/init.dart">'
+    '</script>\' in your page, after all HTML imports.';
+
+const String USE_DART_JS =
+    'To run a polymer applications in Dartium, make sure to include'
+    '\'<script src="packages/browser/dart.js"></script>\' in your page';
+
+const String BOOT_JS_DEPRECATED = 
+    '"boot.js" is now deprecated. Instead, you can initialize your polymer '
+    'application by calling "initPolymer()" in your main. If you don\'t have a '
+    'main, then you can include our generic main by adding the following '
+    'script tag to your page: \'<script type="application/dart" '
+    'src="packages/polymer/init.dart"> </script>\'. Additionally you need to '
+    'include: \'<script src="packages/browser/dart.js"></script>\' in the page '
+    'too. Make sure these script tags come after all HTML imports.';
diff --git a/pkg/polymer/lib/src/build/polyfill_injector.dart b/pkg/polymer/lib/src/build/polyfill_injector.dart
index b8a5afc..3bf7e7a 100644
--- a/pkg/polymer/lib/src/build/polyfill_injector.dart
+++ b/pkg/polymer/lib/src/build/polyfill_injector.dart
@@ -61,25 +61,20 @@
         return;
       }
 
-      if (!jsInteropFound) {
-        // JS interop code is required for Polymer CSS shimming.
+      _addScript(urlSegment) {
         document.body.nodes.insert(0, parseFragment(
-            '<script src="packages/browser/interop.js"></script>\n'));
+              '<script src="packages/$urlSegment"></script>\n'));
       }
 
+      // JS interop code is required for Polymer CSS shimming.
+      if (!jsInteropFound) _addScript('browser/interop.js');
       if (!customElementFound) {
-        document.body.nodes.insert(0, parseFragment(
-            '<script src="packages/custom_element/custom-elements.debug.js">'
-            '</script>\n'));
+        _addScript('custom_element/custom-elements.debug.js');
       }
 
-      if (!shadowDomFound) {
-        // Insert at the beginning (this polyfill needs to run as early as
-        // possible).
-        // TODO(jmesserly): this is .debug to workaround issue 13046.
-        document.body.nodes.insert(0, parseFragment(
-            '<script src="packages/shadow_dom/shadow_dom.debug.js"></script>\n'));
-      }
+      // This polyfill needs to be the first one on the body
+      // TODO(jmesserly): this is .debug to workaround issue 13046.
+      if (!shadowDomFound) _addScript('shadow_dom/shadow_dom.debug.js');
 
       transform.addOutput(
           new Asset.fromString(transform.primaryInput.id, document.outerHtml));
diff --git a/pkg/polymer/lib/src/build/runner.dart b/pkg/polymer/lib/src/build/runner.dart
index 064ac08..c00a7b7 100644
--- a/pkg/polymer/lib/src/build/runner.dart
+++ b/pkg/polymer/lib/src/build/runner.dart
@@ -150,8 +150,8 @@
 
   for (var package in options.packageDirs.keys) {
     // There is nothing to do in the polymer package dependencies.
-    // However: in Polymer package *itself*, we need to replace ObservableMixin
-    // with ChangeNotifierMixin.
+    // However: in Polymer package *itself*, we need to replace Observable
+    // with ChangeNotifier.
     if (!options.transformPolymerDependencies &&
         _polymerPackageDependencies.contains(package)) continue;
     barback.updateTransformers(package, options.phases);
diff --git a/pkg/polymer/lib/src/build/script_compactor.dart b/pkg/polymer/lib/src/build/script_compactor.dart
index 0b4ffca..7ac2b2a 100644
--- a/pkg/polymer/lib/src/build/script_compactor.dart
+++ b/pkg/polymer/lib/src/build/script_compactor.dart
@@ -46,7 +46,8 @@
       for (var tag in document.queryAll('script')) {
         var src = tag.attributes['src'];
         if (src != null) {
-          if (src == 'packages/polymer/boot.js') {
+          if (src == 'packages/polymer/boot.js' ||
+              src == 'packages/polymer/init.dart') {
             tag.remove();
             continue;
           }
@@ -85,10 +86,8 @@
         document.body.nodes.add(bootstrapScript);
         document.body.nodes.add(parseFragment(
             '<script src="packages/browser/dart.js"></script>'));
-      } else if (dartLoaderTag.parent != document.body) {
-        document.body.nodes.add(bootstrapScript);
       } else {
-        document.body.insertBefore(bootstrapScript, dartLoaderTag);
+        dartLoaderTag.parent.insertBefore(bootstrapScript, dartLoaderTag);
       }
 
       var urls = libraries.map((id) => assetUrlFor(id, bootstrapId, logger))
@@ -111,8 +110,6 @@
 library app_bootstrap;
 
 import 'package:polymer/polymer.dart';
-@MirrorsUsed(symbols: 'main', override: 'app_bootstrap')
-import 'dart:mirrors' show currentMirrorSystem, MirrorsUsed;
 """;
 
 const _mainPrefix = """
@@ -121,8 +118,7 @@
   initPolymer([
 """;
 
-// TODO(sigmund): investigate alternative to get the baseUri (dartbug.com/12612)
 const _mainSuffix = """
-    ], currentMirrorSystem().isolate.rootLibrary.uri.toString());
+    ]);
 }
 """;
diff --git a/pkg/polymer/lib/src/instance.dart b/pkg/polymer/lib/src/instance.dart
index dd5c349..0dfefed 100644
--- a/pkg/polymer/lib/src/instance.dart
+++ b/pkg/polymer/lib/src/instance.dart
@@ -408,7 +408,7 @@
 
   void asyncUnbindAll() {
     if (_unbound == true) return;
-    _unbindLog.info('[$localName] asyncUnbindAll');
+    _unbindLog.fine('[$localName] asyncUnbindAll');
     _unbindAllJob = job(_unbindAllJob, unbindAll, const Duration(seconds: 0));
   }
 
@@ -432,7 +432,7 @@
           '[$localName] already unbound, cannot cancel unbindAll');
       return;
     }
-    _unbindLog.info('[$localName] cancelUnbindAll');
+    _unbindLog.fine('[$localName] cancelUnbindAll');
     if (_unbindAllJob != null) {
       _unbindAllJob.stop();
       _unbindAllJob = null;
@@ -491,7 +491,7 @@
   }
 
   void _observe(String name, void callback(newValue, oldValue)) {
-    _observeLog.info('[$localName] watching [$name]');
+    _observeLog.fine('[$localName] watching [$name]');
     // TODO(jmesserly): this is a little different than the JS version so we
     // can pass the oldValue, which is missing from Dart's PathObserver.
     // This probably gives us worse performance.
@@ -565,8 +565,8 @@
   static NodeBinding _bindProperties(Polymer inA, Symbol inProperty,
         Object inB, String inPath) {
 
-    if (_bindLog.isLoggable(Level.INFO)) {
-      _bindLog.info('[$inB]: bindProperties: [$inPath] to '
+    if (_bindLog.isLoggable(Level.FINE)) {
+      _bindLog.fine('[$inB]: bindProperties: [$inPath] to '
           '[${inA.localName}].[$inProperty]');
     }
 
@@ -590,8 +590,8 @@
     var events = _declaration._eventDelegates;
     if (events.isEmpty) return;
 
-    if (_eventsLog.isLoggable(Level.INFO)) {
-      _eventsLog.info('[$localName] addHostListeners: $events');
+    if (_eventsLog.isLoggable(Level.FINE)) {
+      _eventsLog.fine('[$localName] addHostListeners: $events');
     }
     addNodeListeners(this, events.keys, hostEventListener);
   }
@@ -603,8 +603,8 @@
     var events = templateDelegates[template];
     if (events == null) return;
 
-    if (_eventsLog.isLoggable(Level.INFO)) {
-      _eventsLog.info('[$localName] addInstanceListeners: $events');
+    if (_eventsLog.isLoggable(Level.FINE)) {
+      _eventsLog.fine('[$localName] addInstanceListeners: $events');
     }
     addNodeListeners(root, events, instanceEventListener);
   }
@@ -626,14 +626,14 @@
     // https://github.com/Polymer/polymer/issues/292
     if (!event.bubbles) return;
 
-    bool log = _eventsLog.isLoggable(Level.INFO);
+    bool log = _eventsLog.isLoggable(Level.FINE);
     if (log) {
-      _eventsLog.info('>>> [$localName]: hostEventListener(${event.type})');
+      _eventsLog.fine('>>> [$localName]: hostEventListener(${event.type})');
     }
 
     var h = findEventDelegate(event);
     if (h != null) {
-      if (log) _eventsLog.info('[$localName] found host handler name [$h]');
+      if (log) _eventsLog.fine('[$localName] found host handler name [$h]');
       var detail = event is CustomEvent ?
           (event as CustomEvent).detail : null;
       // TODO(jmesserly): cache the symbols?
@@ -641,7 +641,7 @@
     }
 
     if (log) {
-      _eventsLog.info('<<< [$localName]: hostEventListener(${event.type})');
+      _eventsLog.fine('<<< [$localName]: hostEventListener(${event.type})');
     }
   }
 
@@ -651,8 +651,8 @@
   /** Call [methodName] method on [this] with [args], if the method exists. */
   // TODO(jmesserly): I removed the [node] argument as it was unused. Reconcile.
   void dispatchMethod(Symbol methodName, List args) {
-    bool log = _eventsLog.isLoggable(Level.INFO);
-    if (log) _eventsLog.info('>>> [$localName]: dispatch $methodName');
+    bool log = _eventsLog.isLoggable(Level.FINE);
+    if (log) _eventsLog.fine('>>> [$localName]: dispatch $methodName');
 
     // TODO(sigmund): consider making event listeners list all arguments
     // explicitly. Unless VM mirrors are optimized first, this reflectClass call
@@ -669,7 +669,7 @@
     }
     self.invoke(methodName, args);
 
-    if (log) _eventsLog.info('<<< [$localName]: dispatch $methodName');
+    if (log) _eventsLog.fine('<<< [$localName]: dispatch $methodName');
 
     // TODO(jmesserly): workaround for HTML events not supporting zones.
     performMicrotaskCheckpoint();
@@ -686,8 +686,8 @@
     // https://github.com/Polymer/polymer/issues/292
     if (!event.bubbles) return;
 
-    bool log = _eventsLog.isLoggable(Level.INFO);
-    if (log) _eventsLog.info('>>> [$localName]: listenLocal [${event.type}]');
+    bool log = _eventsLog.isLoggable(Level.FINE);
+    if (log) _eventsLog.fine('>>> [$localName]: listenLocal [${event.type}]');
 
     final eventOn = '$_EVENT_PREFIX${_eventNameFromType(event.type)}';
     if (event.path == null) {
@@ -696,7 +696,7 @@
       _listenLocalEventPath(host, event, eventOn);
     }
 
-    if (log) _eventsLog.info('<<< [$localName]: listenLocal [${event.type}]');
+    if (log) _eventsLog.fine('<<< [$localName]: listenLocal [${event.type}]');
   }
 
   static void _listenLocalEventPath(Polymer host, Event event, String eventOn) {
@@ -726,8 +726,8 @@
   static void _listenLocalNoEventPath(Polymer host, Event event,
       String eventOn) {
 
-    if (_eventsLog.isLoggable(Level.INFO)) {
-      _eventsLog.info('event.path() not supported for ${event.type}');
+    if (_eventsLog.isLoggable(Level.FINE)) {
+      _eventsLog.fine('event.path() not supported for ${event.type}');
     }
 
     var target = event.target;
@@ -764,8 +764,8 @@
     // listener, and if so, to determine lazily what's the target method.
     var name = node is Element ? (node as Element).attributes[eventOn] : null;
     if (name != null && _handleIfNotHandled(node, event)) {
-      if (_eventsLog.isLoggable(Level.INFO)) {
-        _eventsLog.info('[${ctrlr.localName}] found handler name [$name]');
+      if (_eventsLog.isLoggable(Level.FINE)) {
+        _eventsLog.fine('[${ctrlr.localName}] found handler name [$name]');
       }
       var detail = event is CustomEvent ?
           (event as CustomEvent).detail : null;
@@ -898,7 +898,7 @@
 
   void _propertyValueChanged(List<ChangeRecord> records) {
     for (var record in records) {
-      if (record.changes(_property)) {
+      if (record is PropertyChangeRecord && record.name == _property) {
         final newValue = _target.getField(_property).reflectee;
         if (!identical(_lastValue, newValue)) {
           value = newValue;
@@ -942,7 +942,7 @@
  *
  * See [Polymer].
  */
-class PolymerElement extends HtmlElement with Polymer, ObservableMixin {
+class PolymerElement extends HtmlElement with Polymer, Observable {
   PolymerElement.created() : super.created() {
     polymerCreated();
   }
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart
index cdc223b..c2e2f55 100644
--- a/pkg/polymer/lib/src/loader.dart
+++ b/pkg/polymer/lib/src/loader.dart
@@ -19,45 +19,125 @@
 /**
  * Initializes a polymer application as follows:
  *   * set up up polling for observable changes
- *   *  initialize MDV
- *   *  for each library in [libraries], register custom elements labeled with
- *      [CustomTag] and invoke the initialization method on it.
+ *   * initialize Model-Driven Views
+ *   * Include some style to prevent flash of unstyled content (FOUC)
+ *   * for each library in [libraries], register custom elements labeled with
+ *      [CustomTag] and invoke the initialization method on it. If [libraries]
+ *      is null, first find all libraries that need to be loaded by scanning for
+ *      HTML imports in the main document.
  *
- * The initialization on each library is either a method named `main` or
- * a top-level function and annotated with [initMethod].
+ * The initialization on each library is a top-level function and annotated with
+ * [initMethod].
  *
- * The urls in [libraries] can be absolute or relative to [srcUrl].
+ * The urls in [libraries] can be absolute or relative to
+ * `currentMirrorSystem().isolate.rootLibrary.uri`.
  */
-void initPolymer(List<String> libraries, [String srcUrl]) {
+void initPolymer([List<String> libraries]) {
   runMicrotask(() {
     // DOM events don't yet go through microtasks, so we catch those here.
     new Timer.periodic(new Duration(milliseconds: 125),
         (_) => performMicrotaskCheckpoint());
 
+    preventFlashOfUnstyledContent();
+
     // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize.
     mdv.initialize();
     document.register(PolymerDeclaration._TAG, PolymerDeclaration);
 
-    for (var lib in libraries) {
-      _loadLibrary(lib, srcUrl);
+    // Note: we synchronously load all libraries because the script invoking
+    // this is run after all HTML imports are resolved.
+    if (libraries == null) {
+      libraries = _discoverScripts(document, window.location.href);
     }
-
-    Polymer._ready.complete();
-
-    // TODO(sigmund): move to boot.dart once it's ready.
-    document.body.style.transition = 'opacity 0.3s';
-    document.body.style.opacity = '1';
+    _loadLibraries(libraries);
   });
 }
 
+void _loadLibraries(libraries) {
+  for (var lib in libraries) {
+    _loadLibrary(lib);
+  }
+  Polymer._ready.complete();
+}
+
+/**
+ * Walks the HTML import structure to discover all script tags that are
+ * implicitly loaded.
+ */
+List<String> _discoverScripts(Document doc, String baseUri,
+    [Set<Document> seen, List<String> scripts]) {
+  if (seen == null) seen = new Set<Document>();
+  if (scripts == null) scripts = <String>[];
+  if (seen.contains(doc)) return scripts;
+  seen.add(doc);
+
+  var inlinedScriptCount = 0;
+  for (var node in doc.queryAll('script,link[rel="import"]')) {
+    if (node is LinkElement) {
+      _discoverScripts(node.import, node.href, seen, scripts);
+    } else if (node is ScriptElement && node.type == 'application/dart') {
+      var url = node.src;
+      if (url != '') {
+        // TODO(sigmund): consider either normalizing package: urls or add a
+        // warning to let users know about cannonicalization issues.
+        scripts.add(url);
+      } else {
+        // We generate a unique identifier for inlined scripts which we later
+        // translate to the unique identifiers used by Dartium. Dartium uses
+        // line/column number information which we can't compute here.
+        scripts.add('$baseUri:$inlinedScriptCount');
+        inlinedScriptCount++;
+      }
+    }
+  }
+  return scripts;
+}
+
 /** All libraries in the current isolate. */
 final _libs = currentMirrorSystem().libraries;
 
+// TODO(sigmund): explore other (cheaper) ways to resolve URIs relative to the
+// root library (see dartbug.com/12612)
+final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri;
+
+/** Regex that matches urls used to represent inlined scripts. */
+final RegExp _inlineScriptRegExp = new RegExp('\(.*\.html.*\):\([0-9]\+\)');
+
+/**
+ * Map URLs fabricated by polymer to URLs fabricated by Dartium to represent
+ * inlined scripts. Polymer uses baseUri:script#, Dartium uses baseUri:line#
+ */
+// TODO(sigmund): figure out if we can generate the same URL and expose it.
+final Map<Uri, List<Uri>> _inlinedScriptMapping = () {
+  var map = {};
+  for (var uri in _libs.keys) {
+    var uriString = uri.toString();
+    var match = _inlineScriptRegExp.firstMatch(uriString);
+    if (match == null) continue;
+    var baseUri = Uri.parse(match.group(1));
+    if (map[baseUri] == null) map[baseUri] = [];
+    map[baseUri].add(uri);
+  }
+  return map;
+}();
+
+/** Returns a new Uri that replaces [path] in [uri]. */
+Uri _replacePath(Uri uri, String path) {
+  return new Uri(scheme: uri.scheme, host: uri.host, port: uri.port,
+      path: path, query: uri.query, fragment: uri.fragment);
+}
+
+/** Returns the Uri in [href] without query parameters or fragments. */
+String _baseUri(String href) {
+  var uri = Uri.parse(window.location.href);
+  var trimUri = new Uri(scheme: uri.scheme, host: uri.host,
+      port: uri.port, path: uri.path);
+  return trimUri.toString();
+}
+
 /**
  * Reads the library at [uriString] (which can be an absolute URI or a relative
- * URI from [srcUrl]), and:
- *
- *   * If present, invokes `main`.
+ * URI from the root library), and:
  *
  *   * If present, invokes any top-level and static functions marked
  *     with the [initMethod] annotation (in the order they appear).
@@ -65,22 +145,25 @@
  *   * Registers any [PolymerElement] that is marked with the [CustomTag]
  *     annotation.
  */
-void _loadLibrary(String uriString, [String srcUrl]) {
-  var uri = Uri.parse(uriString);
-  if (uri.scheme == '' && srcUrl != null) {
-    uri = Uri.parse(path.normalize(path.join(path.dirname(srcUrl), uriString)));
+void _loadLibrary(String uriString) {
+  var uri = _rootUri.resolve(uriString);
+  var lib;
+  var match = _inlineScriptRegExp.firstMatch(uriString);
+  if (match != null) {
+    var baseUri = Uri.parse(match.group(1));
+    var list = _inlinedScriptMapping[baseUri];
+    var pos = int.parse(match.group(2), onError: (_) => -1);
+    if (list != null && pos >= 0 && pos < list.length && list[pos] != null) {
+      lib = _libs[list[pos]];
+    }
+  } else {
+    lib = _libs[uri];
   }
-  var lib = _libs[uri];
   if (lib == null) {
     print('warning: $uri library not found');
     return;
   }
 
-  // Invoke `main`, if present.
-  if (lib.functions[#main] != null) {
-    lib.invoke(#main, const []);
-  }
-
   // Search top-level functions marked with @initMethod
   for (var f in lib.functions.values) {
     _maybeInvoke(lib, f);
diff --git a/pkg/polymer/lib/transformer.dart b/pkg/polymer/lib/transformer.dart
index 26d5678..a0e4902 100644
--- a/pkg/polymer/lib/transformer.dart
+++ b/pkg/polymer/lib/transformer.dart
@@ -25,7 +25,7 @@
   return [
     [new InlineCodeExtractor(options)],
     [new ObservableTransformer()],
-    [new ImportedElementInliner(options)],
+    [new ImportInliner(options)],
     [new ScriptCompactor(options)],
     [new PolyfillInjector(options)]
   ];
diff --git a/pkg/polymer/test/attr_deserialize_test.dart b/pkg/polymer/test/attr_deserialize_test.dart
index d69fb5e..911435d 100644
--- a/pkg/polymer/test/attr_deserialize_test.dart
+++ b/pkg/polymer/test/attr_deserialize_test.dart
@@ -19,7 +19,7 @@
   @published Object json;
 }
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   test('attributes were deserialized', () {
diff --git a/pkg/polymer/test/attr_deserialize_test.html b/pkg/polymer/test/attr_deserialize_test.html
index de10fac..48c2102 100644
--- a/pkg/polymer/test/attr_deserialize_test.html
+++ b/pkg/polymer/test/attr_deserialize_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>Polymer.dart attribute deserialization test</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
   <body>
@@ -25,5 +24,6 @@
     </my-element>
 
     <script type="application/dart" src="attr_deserialize_test.dart"></script>
+    <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/attr_mustache_test.dart b/pkg/polymer/test/attr_mustache_test.dart
index 69456e8..50753b3 100644
--- a/pkg/polymer/test/attr_mustache_test.dart
+++ b/pkg/polymer/test/attr_mustache_test.dart
@@ -43,7 +43,7 @@
   @observable var src = 'testSource';
 }
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   test('mustache attributes', () {
diff --git a/pkg/polymer/test/attr_mustache_test.html b/pkg/polymer/test/attr_mustache_test.html
index df9f9ee..b4ef0e2 100644
--- a/pkg/polymer/test/attr_mustache_test.html
+++ b/pkg/polymer/test/attr_mustache_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>take attributes</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
   <body>
@@ -23,5 +22,6 @@
     </polymer-element>
 
   <script type="application/dart" src="attr_mustache_test.dart"></script>
+  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/build/all_phases_test.dart b/pkg/polymer/test/build/all_phases_test.dart
index e977893..047dca4 100644
--- a/pkg/polymer/test/build/all_phases_test.dart
+++ b/pkg/polymer/test/build/all_phases_test.dart
@@ -51,7 +51,7 @@
           void main() {
             initPolymer([
                 'a.dart',
-              ], currentMirrorSystem().isolate.rootLibrary.uri.toString());
+              ]);
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/test.dart': _sampleObservableOutput('A', 'foo'),
@@ -80,7 +80,7 @@
           void main() {
             initPolymer([
                 'test.html.0.dart',
-              ], currentMirrorSystem().isolate.rootLibrary.uri.toString());
+              ]);
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/test.html.0.dart': _sampleObservableOutput("B", "bar"),
@@ -123,7 +123,7 @@
                 'test.html.0.dart',
                 'test.html.1.dart',
                 'd.dart',
-              ], currentMirrorSystem().isolate.rootLibrary.uri.toString());
+              ]);
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/a.dart': _sampleObservableOutput('A', 'foo'),
@@ -168,7 +168,7 @@
                 'test2.html.0.dart',
                 'b.dart',
                 'index.html.0.dart',
-              ], currentMirrorSystem().isolate.rootLibrary.uri.toString());
+              ]);
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/test2.html.0.dart': _sampleObservableOutput("A", "foo"),
@@ -181,7 +181,7 @@
 library ${className}_$fieldName;
 import 'package:observe/observe.dart';
 
-class $className extends ObservableBase {
+class $className extends Observable {
   @observable int $fieldName;
   $className(this.$fieldName);
 }
@@ -190,7 +190,7 @@
 String _sampleObservableOutput(String className, String field) =>
     "library ${className}_$field;\n"
     "import 'package:observe/observe.dart';\n\n"
-    "class $className extends ChangeNotifierBase {\n"
+    "class $className extends ChangeNotifier {\n"
     "  @reflectable @observable int get $field => __\$$field; "
       "int __\$$field; "
       "@reflectable set $field(int value) { "
diff --git a/pkg/polymer/test/build/import_inliner_test.dart b/pkg/polymer/test/build/import_inliner_test.dart
index 8654107..b40eea5 100644
--- a/pkg/polymer/test/build/import_inliner_test.dart
+++ b/pkg/polymer/test/build/import_inliner_test.dart
@@ -13,7 +13,7 @@
 
 void main() {
   useCompactVMConfiguration();
-  var phases = [[new ImportedElementInliner(new TransformOptions())]];
+  var phases = [[new ImportInliner(new TransformOptions())]];
   testPhases('no changes', phases, {
       'a|web/test.html': '<!DOCTYPE html><html></html>',
     }, {
@@ -266,6 +266,45 @@
           '<polymer-element>2</polymer-element></body></html>',
     });
 
+  testPhases('imports cycle, 1-step lasso, scripts too', phases, {
+      'a|web/test.html':
+          '<!DOCTYPE html><html><head>'
+          '<link rel="import" href="test_1.html">'
+          '</head></html>',
+      'a|web/test_1.html':
+          '<!DOCTYPE html><html><head>'
+          '<link rel="import" href="test_2.html">'
+          '</head><body><polymer-element>1</polymer-element>'
+          '<script src="s1"></script></html>',
+      'a|web/test_2.html':
+          '<!DOCTYPE html><html><head>'
+          '<link rel="import" href="test_1.html">'
+          '</head><body><polymer-element>2</polymer-element>'
+          '<script src="s2"></script></html>',
+    }, {
+      'a|web/test.html':
+          '<!DOCTYPE html><html><head>'
+          '</head><body>'
+          '<polymer-element>2</polymer-element>'
+          '<script src="s2"></script>'
+          '<polymer-element>1</polymer-element>'
+          '<script src="s1"></script></body></html>',
+      'a|web/test_1.html':
+          '<!DOCTYPE html><html><head>'
+          '</head><body>'
+          '<polymer-element>2</polymer-element>'
+          '<script src="s2"></script>'
+          '<polymer-element>1</polymer-element>'
+          '<script src="s1"></script></body></html>',
+      'a|web/test_2.html':
+          '<!DOCTYPE html><html><head>'
+          '</head><body>'
+          '<polymer-element>1</polymer-element>'
+          '<script src="s1"></script>'
+          '<polymer-element>2</polymer-element>'
+          '<script src="s2"></script></body></html>',
+    });
+
   testPhases('imports cycle, 2-step lasso', phases, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
diff --git a/pkg/polymer/test/build/linter_test.dart b/pkg/polymer/test/build/linter_test.dart
index 17975a8..98f4c3f 100644
--- a/pkg/polymer/test/build/linter_test.dart
+++ b/pkg/polymer/test/build/linter_test.dart
@@ -15,18 +15,51 @@
 void main() {
   useCompactVMConfiguration();
   _testLinter('nothing to report', {
-      'a|web/test.html': '<!DOCTYPE html><html></html>',
+      'a|lib/test.html': '<!DOCTYPE html><html></html>',
     }, {
-      'a|web/test.html.messages': '',
+      'a|lib/test.html.messages': ''
     });
 
+  group('must use init.dart, dart.js, not boot.js', () {
+    _testLinter('nothing to report', {
+        'a|web/test.html': '<!DOCTYPE html><html>'
+            '<script type="application/dart" src="packages/polymer/init.dart">'
+            '</script>'
+            '<script src="packages/browser/dart.js"></script>'
+            '</html>',
+      }, {
+        'a|web/test.html.messages': '',
+      });
+
+    _testLinter('missing init.dart and dart.js', {
+        'a|web/test.html': '<!DOCTYPE html><html></html>',
+      }, {
+        'a|web/test.html.messages': 'error: $USE_INIT_DART\n'
+                                    'error: $USE_DART_JS',
+      });
+
+    _testLinter('using deprecated boot.js', {
+        'a|web/test.html': '<!DOCTYPE html><html>\n'
+            '<script src="packages/polymer/boot.js"></script>'
+            '<script type="application/dart" src="packages/polymer/init.dart">'
+            '</script>'
+            '<script src="packages/browser/dart.js"></script>'
+            '</html>',
+      }, {
+        'a|web/test.html.messages': 'warning: $BOOT_JS_DEPRECATED '
+                                    '(web/test.html 1 0)',
+      });
+  });
+
   group('doctype warning', () {
     _testLinter('in web', {
         'a|web/test.html': '<html></html>',
       }, {
         'a|web/test.html.messages':
             'warning: Unexpected start tag (html). Expected DOCTYPE. '
-            '(web/test.html 0 0)',
+            '(web/test.html 0 0)\n'
+            'error: $USE_INIT_DART\n'
+            'error: $USE_DART_JS',
       });
 
     _testLinter('in lib', {
diff --git a/pkg/polymer/test/build/script_compactor_test.dart b/pkg/polymer/test/build/script_compactor_test.dart
index e0977be..74eab9e 100644
--- a/pkg/polymer/test/build/script_compactor_test.dart
+++ b/pkg/polymer/test/build/script_compactor_test.dart
@@ -49,7 +49,7 @@
           void main() {
             initPolymer([
                 'a.dart',
-              ], currentMirrorSystem().isolate.rootLibrary.uri.toString());
+              ]);
           }
           '''.replaceAll('\n          ', '\n'),
     });
@@ -84,7 +84,7 @@
                 'b.dart',
                 'c.dart',
                 'd.dart',
-              ], currentMirrorSystem().isolate.rootLibrary.uri.toString());
+              ]);
           }
           '''.replaceAll('\n          ', '\n'),
     });
diff --git a/pkg/polymer/test/event_path_test.dart b/pkg/polymer/test/event_path_test.dart
index 660566a..3351502 100644
--- a/pkg/polymer/test/event_path_test.dart
+++ b/pkg/polymer/test/event_path_test.dart
@@ -9,7 +9,7 @@
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
diff --git a/pkg/polymer/test/event_path_test.html b/pkg/polymer/test/event_path_test.html
index f8fa059..fff93dd 100644
--- a/pkg/polymer/test/event_path_test.html
+++ b/pkg/polymer/test/event_path_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>event path</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
     <!--
     Test ported from:
@@ -90,5 +89,6 @@
 
 
   <script type="application/dart" src="event_path_test.dart"></script>
+  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/events_test.dart b/pkg/polymer/test/events_test.dart
index ea35149..2b936a8 100644
--- a/pkg/polymer/test/events_test.dart
+++ b/pkg/polymer/test/events_test.dart
@@ -9,7 +9,7 @@
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
diff --git a/pkg/polymer/test/events_test.html b/pkg/polymer/test/events_test.html
index 88aba17..54bce09 100644
--- a/pkg/polymer/test/events_test.html
+++ b/pkg/polymer/test/events_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>event path</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
     <!--
     Test ported from:
@@ -62,5 +61,6 @@
   <test-b id="b"></test-b>
 
   <script type="application/dart" src="events_test.dart"></script>
+  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/instance_attrs_test.dart b/pkg/polymer/test/instance_attrs_test.dart
index 7103079..45508bc 100644
--- a/pkg/polymer/test/instance_attrs_test.dart
+++ b/pkg/polymer/test/instance_attrs_test.dart
@@ -11,9 +11,13 @@
 @CustomTag('my-element')
 class MyElement extends PolymerElement {
   MyElement.created() : super.created();
+
+  // This is here so that [attributes] can be read via mirrors in polymer
+  // expressions (@CustomTag in this class makes the attribute reflectable).
+  get attributes => super.attributes;
 }
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   test('attributes were deserialized', () {
diff --git a/pkg/polymer/test/instance_attrs_test.html b/pkg/polymer/test/instance_attrs_test.html
index 6665a9e..b8f3b23 100644
--- a/pkg/polymer/test/instance_attrs_test.html
+++ b/pkg/polymer/test/instance_attrs_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>Polymer.dart attribute deserialization test</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
   <body>
@@ -22,5 +21,6 @@
     <my-element baz="world"></my-element>
 
     <script type="application/dart" src="instance_attrs_test.dart"></script>
+    <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/prop_attr_bind_reflection_test.dart b/pkg/polymer/test/prop_attr_bind_reflection_test.dart
index 0acc2a1..7ae9a7f 100644
--- a/pkg/polymer/test/prop_attr_bind_reflection_test.dart
+++ b/pkg/polymer/test/prop_attr_bind_reflection_test.dart
@@ -27,7 +27,7 @@
   MyElement.created() : super.created();
 }
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
diff --git a/pkg/polymer/test/prop_attr_bind_reflection_test.html b/pkg/polymer/test/prop_attr_bind_reflection_test.html
index 8968571..53949ef 100644
--- a/pkg/polymer/test/prop_attr_bind_reflection_test.html
+++ b/pkg/polymer/test/prop_attr_bind_reflection_test.html
@@ -2,7 +2,6 @@
 <html>
   <head>
     <title>property to attribute reflection with bind</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
 
@@ -29,5 +28,6 @@
 
     <script type="application/dart" src="prop_attr_bind_reflection_test.dart">
     </script>
+    <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/prop_attr_reflection_test.dart b/pkg/polymer/test/prop_attr_reflection_test.dart
index 5e0566d..3fd29fd 100644
--- a/pkg/polymer/test/prop_attr_reflection_test.dart
+++ b/pkg/polymer/test/prop_attr_reflection_test.dart
@@ -30,7 +30,7 @@
   @observable bool zim = false;
 }
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   // Most tests use @CustomTag, here we test out the impertive register:
diff --git a/pkg/polymer/test/prop_attr_reflection_test.html b/pkg/polymer/test/prop_attr_reflection_test.html
index e4466d3..1f86f45 100644
--- a/pkg/polymer/test/prop_attr_reflection_test.html
+++ b/pkg/polymer/test/prop_attr_reflection_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>publish attributes</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
   <body>
@@ -28,5 +27,6 @@
     </polymer-element>
 
   <script type="application/dart" src="prop_attr_reflection_test.dart"></script>
+  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/pkg/polymer/test/publish_attributes_test.dart b/pkg/polymer/test/publish_attributes_test.dart
index 7aab5cc..b07df0c 100644
--- a/pkg/polymer/test/publish_attributes_test.dart
+++ b/pkg/polymer/test/publish_attributes_test.dart
@@ -41,7 +41,7 @@
   @published int squid = 7;
 }
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   test('published properties', () {
diff --git a/pkg/polymer/test/publish_attributes_test.html b/pkg/polymer/test/publish_attributes_test.html
index 6b9347a..b79329d 100644
--- a/pkg/polymer/test/publish_attributes_test.html
+++ b/pkg/polymer/test/publish_attributes_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>publish attributes</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
   <body>
@@ -25,5 +24,6 @@
     </polymer-element>
 
   <script type="application/dart" src="publish_attributes_test.dart"></script>
+  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/run.sh b/pkg/polymer/test/run.sh
index 7c20556..f57855c 100755
--- a/pkg/polymer/test/run.sh
+++ b/pkg/polymer/test/run.sh
@@ -16,7 +16,7 @@
 
 SUITES="pkg/polymer samples/third_party/todomvc"
 
-CONFIG="-m release -r vm,drt,ff,chrome -c none,dart2js,dartanalyzer --checked $*"
+CONFIG="-m release -r vm,drt,ff,chrome,d8,jsshell -c none,dart2js,dartanalyzer --checked $*"
 
 CMD="xvfb-run ./tools/test.py $CONFIG $SUITES"
 echo "*** $CMD"
diff --git a/pkg/polymer/test/take_attributes_test.dart b/pkg/polymer/test/take_attributes_test.dart
index a17eecb..9dc0023f 100644
--- a/pkg/polymer/test/take_attributes_test.dart
+++ b/pkg/polymer/test/take_attributes_test.dart
@@ -49,7 +49,7 @@
   @observable var values = {};
 }
 
-main() {
+@initMethod _main() {
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
diff --git a/pkg/polymer/test/take_attributes_test.html b/pkg/polymer/test/take_attributes_test.html
index c65f604..941051c 100644
--- a/pkg/polymer/test/take_attributes_test.html
+++ b/pkg/polymer/test/take_attributes_test.html
@@ -7,7 +7,6 @@
 <html>
   <head>
     <title>take attributes</title>
-    <script src="packages/polymer/boot.js"></script>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
   <body>
@@ -71,5 +70,6 @@
     </x-obj>
 
   <script type="application/dart" src="take_attributes_test.dart"></script>
+  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer_expressions/example/person.dart b/pkg/polymer_expressions/example/person.dart
index c77f5b8..aeb6bd0 100644
--- a/pkg/polymer_expressions/example/person.dart
+++ b/pkg/polymer_expressions/example/person.dart
@@ -6,7 +6,7 @@
 
 import 'package:observe/observe.dart';
 
-class Person extends ChangeNotifierBase {
+class Person extends ChangeNotifier {
   String _firstName;
   String _lastName;
   List<String> _items;
diff --git a/pkg/polymer_expressions/lib/eval.dart b/pkg/polymer_expressions/lib/eval.dart
index 5c0c6e4..4f624b1 100644
--- a/pkg/polymer_expressions/lib/eval.dart
+++ b/pkg/polymer_expressions/lib/eval.dart
@@ -420,20 +420,20 @@
 
   IdentifierObserver(Identifier value) : super(value);
 
-  dynamic get value => _expr.value;
+  String get value => (_expr as Identifier).value;
 
   _updateSelf(Scope scope) {
-    _value = scope[_expr.value];
+    _value = scope[value];
 
-    var owner = scope.ownerOf(_expr.value);
+    var owner = scope.ownerOf(value);
     if (owner is Observable) {
-      _subscription = (owner as Observable).changes.listen(
-          (List<ChangeRecord> changes) {
-            var symbol = new Symbol(_expr.value);
-            if (changes.any((c) => c.changes(symbol))) {
-              _invalidate(scope);
-            }
-          });
+      var symbol = new Symbol(value);
+      _subscription = (owner as Observable).changes.listen((changes) {
+        if (changes.any(
+            (c) => c is PropertyChangeRecord && c.name == symbol)) {
+          _invalidate(scope);
+        }
+      });
     }
   }
 
@@ -545,7 +545,7 @@
           _subscription = (receiverValue as Observable).changes.listen(
               (List<ChangeRecord> changes) {
                 if (changes.any((c) =>
-                    c is MapChangeRecord && c.changes(key))) {
+                    c is MapChangeRecord && c.key == key)) {
                   _invalidate(scope);
                 }
               });
@@ -560,7 +560,8 @@
         if (receiverValue is Observable) {
           _subscription = (receiverValue as Observable).changes.listen(
               (List<ChangeRecord> changes) {
-                if (changes.any((c) => c.changes(symbol))) {
+                if (changes.any(
+                    (c) => c is PropertyChangeRecord && c.name == symbol)) {
                   _invalidate(scope);
                 }
               });
diff --git a/pkg/polymer_expressions/lib/polymer_expressions.dart b/pkg/polymer_expressions/lib/polymer_expressions.dart
index 11d4aeb..02d2afb 100644
--- a/pkg/polymer_expressions/lib/polymer_expressions.dart
+++ b/pkg/polymer_expressions/lib/polymer_expressions.dart
@@ -90,7 +90,7 @@
   }
 }
 
-class _Binding extends ChangeNotifierBase {
+class _Binding extends ChangeNotifier {
   final Scope _scope;
   final ExpressionObserver _expr;
   final _converter;
@@ -133,7 +133,7 @@
     try {
       assign(_expr, v, _scope);
     } on EvalException catch (e) {
-      // silently swallow binding errors
+      _logger.warning("Error evaluating expression '$_expr': ${e.message}");
     }
   }
 }
diff --git a/pkg/polymer_expressions/test/bindings_test.dart b/pkg/polymer_expressions/test/bindings_test.dart
index e63ee04..cf37e1d 100644
--- a/pkg/polymer_expressions/test/bindings_test.dart
+++ b/pkg/polymer_expressions/test/bindings_test.dart
@@ -5,6 +5,8 @@
 library bindings_test;
 
 import 'dart:html';
+
+import 'package:logging/logging.dart';
 import 'package:mdv/mdv.dart' as mdv;
 import 'package:observe/observe.dart';
 import 'package:observe/src/microtask.dart';
@@ -16,18 +18,63 @@
   mdv.initialize();
   useHtmlConfiguration();
 
-  group('cursor position tests', () {
+  group('bindings', () {
+    var stop = null;
+    var messages = [];
     var testDiv;
     setUp(() {
+      stop = Logger.root.onRecord.listen((r) => messages.add(r));
       document.body.append(testDiv = new DivElement());
     });
 
     tearDown(() {
       testDiv.remove();
       testDiv = null;
+      stop.cancel();
+      stop = null;
+      messages = [];
     });
 
-    test('cursor position test', wrapMicrotask(() {
+    observeTest('should update binding when data changes', () {
+      var model = new NotifyModel();
+      var binding = new PolymerExpressions()
+          .getBinding(model, 'x', null, null);
+      expect(binding.value, isNull);
+      model.x = "hi";
+      performMicrotaskCheckpoint();
+      expect(binding.value, 'hi');
+      expect(messages.length, 0);
+    });
+
+    observeTest('should update text content when data changes', () {
+      var model = new NotifyModel('abcde');
+      var template = new Element.html(
+          '<template><span>{{x}}</span></template>');
+      testDiv.append(template.createInstance(model, new PolymerExpressions()));
+
+      performMicrotaskCheckpoint();
+      var el = testDiv.query("span");
+      expect(el.text, 'abcde');
+      expect(model.x, 'abcde');
+      model.x = '___';
+
+      performMicrotaskCheckpoint();
+      expect(model.x, '___');
+      expect(el.text, '___');
+    });
+
+    observeTest('should log eval exceptions', () {
+      var model = new NotifyModel('abcde');
+      var template = new Element.html(
+          '<template><span>{{foo}}</span></template>');
+      testDiv.append(template.createInstance(model, new PolymerExpressions()));
+      performMicrotaskCheckpoint();
+      expect(messages.length, 1);
+      expect(messages[0].message,
+          "Error evaluating expression 'foo': variable 'foo' not found");
+    });
+
+    observeTest('should preserve the cursor position', () {
       var model = new NotifyModel('abcde');
       var template = new Element.html(
           '<template><input id="i1" value={{x}}></template>');
@@ -68,17 +115,19 @@
       expect(el.selectionEnd, 4);
 
       subscription.cancel();
-    }));
+    });
   });
 }
 
 @reflectable
-class NotifyModel extends ChangeNotifierBase {
+class NotifyModel extends ChangeNotifier {
   var _x;
   NotifyModel([this._x]);
 
   get x => _x;
   set x(value) {
-    _x = notifyPropertyChange(const Symbol('x'), _x, value);
+    _x = notifyPropertyChange(#x, _x, value);
   }
 }
+
+observeTest(name, testCase) => test(name, wrapMicrotask(testCase));
diff --git a/pkg/polymer_expressions/test/eval_test.dart b/pkg/polymer_expressions/test/eval_test.dart
index f18ccec..87ecb3b 100644
--- a/pkg/polymer_expressions/test/eval_test.dart
+++ b/pkg/polymer_expressions/test/eval_test.dart
@@ -330,7 +330,7 @@
 }
 
 @reflectable
-class Foo extends ChangeNotifierBase {
+class Foo extends ChangeNotifier {
   String _name;
   String get name => _name;
   void set name(String n) {
@@ -398,7 +398,7 @@
 }
 
 // Regression test from https://code.google.com/p/dart/issues/detail?id=13459
-class WordElement extends ObservableBase {
+class WordElement extends Observable {
   @observable List chars1 = 'abcdefg'.split('');
   @reflectable List filteredList(List original) => [original[0], original[1]];
 }
diff --git a/pkg/polymer_expressions/test/syntax_test.dart b/pkg/polymer_expressions/test/syntax_test.dart
index ceb1307..c0a92e1 100644
--- a/pkg/polymer_expressions/test/syntax_test.dart
+++ b/pkg/polymer_expressions/test/syntax_test.dart
@@ -83,7 +83,7 @@
 }
 
 @reflectable
-class Person extends ChangeNotifierBase {
+class Person extends ChangeNotifier {
   String _firstName;
   String _lastName;
   List<String> _items;
diff --git a/pkg/stack_trace/lib/src/frame.dart b/pkg/stack_trace/lib/src/frame.dart
index 797bef1..0b4f577 100644
--- a/pkg/stack_trace/lib/src/frame.dart
+++ b/pkg/stack_trace/lib/src/frame.dart
@@ -23,12 +23,12 @@
 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560
 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560
 final _firefoxFrame = new RegExp(
-    r'^([^@(/]*)(?:\(.*\))?(/[^<]*<?)?(?:\(.*\))?@(.*):(\d+)$');
+    r'^([^@(/]*)(?:\(.*\))?((?:/[^/]*)*)(?:\(.*\))?@(.*):(\d+)$');
 
 // foo/bar.dart 10:11 in Foo._bar
 // http://dartlang.org/foo/bar.dart in Foo._bar
 final _friendlyFrame = new RegExp(
-    r'^([^\s]+)(?: (\d+):(\d+))?\s+([^\d][^\s]*)$');
+    r'^([^\s]+)(?: (\d+)(?::(\d+))?)?\s+([^\d][^\s]*)$');
 
 final _initialDot = new RegExp(r"^\.");
 
@@ -78,7 +78,8 @@
 
   /// A human-friendly description of the code location.
   String get location {
-    if (line == null || column == null) return library;
+    if (line == null) return library;
+    if (column == null) return '$library $line';
     return '$library $line:$column';
   }
 
@@ -159,11 +160,9 @@
 
     var uri = Uri.parse(match[3]);
     var member = match[1];
-    if (member == "") {
-      member = "<fn>";
-    } else if (match[2] != null) {
-      member = "$member.<fn>";
-    }
+    member += new List.filled('/'.allMatches(match[2]).length, ".<fn>").join();
+    if (member == '') member = '<fn>';
+
     // Some Firefox members have initial dots. We remove them for consistency
     // with other platforms.
     member = member.replaceFirst(_initialDot, '');
diff --git a/pkg/stack_trace/lib/src/lazy_trace.dart b/pkg/stack_trace/lib/src/lazy_trace.dart
index ae56b5f..874123e 100644
--- a/pkg/stack_trace/lib/src/lazy_trace.dart
+++ b/pkg/stack_trace/lib/src/lazy_trace.dart
@@ -30,4 +30,7 @@
   Trace foldFrames(bool predicate(frame)) =>
     new LazyTrace(() => _trace.foldFrames(predicate));
   String toString() => _trace.toString();
+
+  // Work around issue 14075.
+  set frames(_) => throw new UnimplementedError();
 }
diff --git a/pkg/stack_trace/lib/src/trace.dart b/pkg/stack_trace/lib/src/trace.dart
index bf14ee2..95d41ad 100644
--- a/pkg/stack_trace/lib/src/trace.dart
+++ b/pkg/stack_trace/lib/src/trace.dart
@@ -36,7 +36,7 @@
 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+)?)?\s+[^\s]+($|\n)");
 
 /// A stack trace, comprised of a list of stack frames.
 class Trace implements StackTrace {
diff --git a/pkg/stack_trace/test/frame_test.dart b/pkg/stack_trace/test/frame_test.dart
index 62cfd2e..ab7c401 100644
--- a/pkg/stack_trace/test/frame_test.dart
+++ b/pkg/stack_trace/test/frame_test.dart
@@ -202,6 +202,18 @@
       expect(frame.member, equals("foo.<fn>"));
     });
 
+    test('parses a deeply-nested anonymous stack frame with parameters '
+        'correctly', () {
+      var frame = new Frame.parseFirefox(
+          '.convertDartClosureToJS/\$function</<@'
+          'http://pub.dartlang.org/stuff.dart.js:560');
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("convertDartClosureToJS.<fn>.<fn>"));
+    });
+
     test('throws a FormatException for malformed frames', () {
       expect(() => new Frame.parseFirefox(''), throwsFormatException);
       expect(() => new Frame.parseFirefox('.foo'), throwsFormatException);
@@ -233,6 +245,15 @@
       expect(frame.member, equals('Foo.<fn>.bar'));
     });
 
+    test('parses a stack frame with no line correctly', () {
+      var frame = new Frame.parseFriendly(
+          "http://dartlang.org/foo/bar.dart 10  Foo.<fn>.bar");
+      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.<fn>.bar'));
+    });
+
     test('parses a stack frame with a relative path correctly', () {
       var frame = new Frame.parseFriendly("foo/bar.dart 10:11    Foo.<fn>.bar");
       expect(frame.uri, equals(
@@ -321,5 +342,10 @@
               '(dart:core/uri.dart:5:10)').toString(),
           equals('dart:core/uri.dart 5:10 in Foo.<fn>'));
     });
+
+    test('prints a frame without a column correctly', () {
+      expect(new Frame.parseVM('#0 Foo (dart:core/uri.dart:5)').toString(),
+          equals('dart:core/uri.dart 5 in Foo'));
+    });
   });
 }
diff --git a/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart b/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
index 9cac0b3..9fd35e8 100644
--- a/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
+++ b/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
@@ -84,7 +84,9 @@
    * Throws an [UnsupportedError];
    * operations that change the length of the list are disallowed.
    */
-  void add(E value) => _throw();
+  bool add(E value) {
+    _throw();
+  }
 
   /**
    * Throws an [UnsupportedError];
@@ -185,7 +187,9 @@
    * Throws an [UnsupportedError];
    * operations that change the set are disallowed.
    */
-  void add(E value) => _throw();
+  bool add(E value) {
+    _throw();
+  }
 
   /**
    * Throws an [UnsupportedError];
diff --git a/runtime/bin/builtin_nolib.cc b/runtime/bin/builtin_nolib.cc
index 214caba..b19dfd3 100644
--- a/runtime/bin/builtin_nolib.cc
+++ b/runtime/bin/builtin_nolib.cc
@@ -22,17 +22,19 @@
 
 
 Dart_Handle Builtin::Source(BuiltinLibraryId id) {
-  return Dart_NewApiError("Unreachable code in Builtin::Source (%d).", id);
+  return DartUtils::NewError("Unreachable code in Builtin::Source (%d).", id);
 }
 
 
 Dart_Handle Builtin::PartSource(BuiltinLibraryId id, const char* uri) {
-  return Dart_NewApiError("Unreachable code in Builtin::PartSource (%d).", id);
+  return DartUtils::NewError(
+      "Unreachable code in Builtin::PartSource (%d).", id);
 }
 
 
 Dart_Handle Builtin::GetSource(const char** source_paths, const char* uri) {
-  return Dart_NewApiError("Unreachable code in Builtin::GetSource (%s).", uri);
+  return DartUtils::NewError(
+      "Unreachable code in Builtin::GetSource (%s).", uri);
 }
 
 
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 41a06e6..657a457 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -176,15 +176,15 @@
   // Get the url of the including library.
   Dart_Handle library_url = Dart_LibraryUrl(library);
   if (Dart_IsError(library_url)) {
-    return Dart_Error("accessing library url failed");
+    return Dart_NewApiError("accessing library url failed");
   }
   if (!Dart_IsString(library_url)) {
-    return Dart_Error("library url is not a string");
+    return Dart_NewApiError("library url is not a string");
   }
   const char* library_url_str = NULL;
   Dart_Handle result = Dart_StringToCString(library_url, &library_url_str);
   if (Dart_IsError(result)) {
-    return Dart_Error("accessing library url characters failed");
+    return Dart_NewApiError("accessing library url characters failed");
   }
   if (url_mapping != NULL) {
     const char* mapped_library_url_str = MapLibraryUrl(url_mapping,
@@ -292,9 +292,9 @@
       return responseStatus;
     }
     if (Dart_IsNull(responseStatus)) {
-      return Dart_Error("HTTP error.");
+      return Dart_NewApiError("HTTP error.");
     }
-    return Dart_Error(DartUtils::GetStringValue(responseStatus));
+    return Dart_NewApiError(DartUtils::GetStringValue(responseStatus));
   }
   Dart_Handle response =
       Dart_Invoke(builtin_lib, DartUtils::NewString("_getHttpRequestResponse"),
@@ -386,7 +386,7 @@
   intptr_t len;
   const uint8_t* text_buffer = ReadFileFully(filename, &len, &error_msg);
   if (text_buffer == NULL) {
-    return Dart_Error(error_msg);
+    return Dart_NewApiError(error_msg);
   }
   Dart_Handle str = Dart_NewStringFromUTF8(text_buffer, len);
   free(const_cast<uint8_t *>(text_buffer));
@@ -440,10 +440,10 @@
                                          Dart_Handle library,
                                          Dart_Handle url) {
   if (!Dart_IsLibrary(library)) {
-    return Dart_Error("not a library");
+    return Dart_NewApiError("not a library");
   }
   if (!Dart_IsString(url)) {
-    return Dart_Error("url is not a string");
+    return Dart_NewApiError("url is not a string");
   }
   const char* url_string = NULL;
   Dart_Handle result = Dart_StringToCString(url, &url_string);
@@ -485,11 +485,11 @@
       if (DartUtils::IsDartIOLibURL(url_string)) {
         return Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
       }
-      return Dart_Error("The built-in library '%s' is not available"
-                        " on the stand-alone VM.\n", url_string);
+      return NewError("The built-in library '%s' is not available"
+                      " on the stand-alone VM.\n", url_string);
     } else {
       ASSERT(tag == Dart_kSourceTag);
-      return Dart_Error("Unable to load source '%s' ", url_string);
+      return NewError("Unable to load source '%s' ", url_string);
     }
   }
 
@@ -500,7 +500,7 @@
           library, url, Builtin::PartSource(Builtin::kIOLibrary, url_string));
     } else {
       ASSERT(tag == Dart_kImportTag);
-      return Dart_Error("Unable to import '%s' ", url_string);
+      return NewError("Unable to import '%s' ", url_string);
     }
   }
 
@@ -515,7 +515,7 @@
   Dart_StringToCString(file_path, &url_string);
   if (is_dart_extension_url) {
     if (tag != Dart_kImportTag) {
-      return Dart_Error("Dart extensions must use import: '%s'", url_string);
+      return NewError("Dart extensions must use import: '%s'", url_string);
     }
     return Extensions::LoadExtension(url_string, library);
   }
@@ -600,7 +600,7 @@
                                         &len,
                                         &error_msg);
   if (buffer == NULL) {
-    return Dart_Error(error_msg);
+    return Dart_NewApiError(error_msg);
   }
   bool is_snapshot = false;
   const uint8_t *payload = SniffForMagicNumber(buffer, &len, &is_snapshot);
@@ -629,7 +629,7 @@
   if (url_mapping != NULL && IsDartSchemeURL(url_string)) {
     const char* mapped_url_string = MapLibraryUrl(url_mapping, url_string);
     if (mapped_url_string == NULL) {
-      return Dart_Error("Do not know how to load %s", url_string);
+      return NewError("Do not know how to load %s", url_string);
     }
     // We have a URL mapping specified, just read the file that the
     // URL mapping specifies and load it.
@@ -654,7 +654,7 @@
   } else if (tag == Dart_kSourceTag) {
     return Dart_LoadSource(library, url, source);
   }
-  return Dart_Error("wrong tag");
+  return Dart_NewApiError("wrong tag");
 }
 
 
@@ -853,6 +853,22 @@
 }
 
 
+Dart_Handle DartUtils::NewError(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  intptr_t len = vsnprintf(NULL, 0, format, args);
+  va_end(args);
+
+  char* buffer = reinterpret_cast<char*>(Dart_ScopeAllocate(len + 1));
+  va_list args2;
+  va_start(args2, format);
+  vsnprintf(buffer, (len + 1), format, args2);
+  va_end(args2);
+
+  return Dart_NewApiError(buffer);
+}
+
+
 Dart_Handle DartUtils::NewInternalError(const char* message) {
   return NewDartExceptionWithMessage(kCoreLibURL, "_InternalError", message);
 }
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index e157fad..6540454 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -161,6 +161,7 @@
   }
 
   // Create a new Dart InternalError object with the provided message.
+  static Dart_Handle NewError(const char* format, ...);
   static Dart_Handle NewInternalError(const char* message);
 
   static bool SetOriginalWorkingDirectory();
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 51e98ac..334d496 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -818,7 +818,7 @@
 
       Handle::ScopedLock lock(listen_socket);
 
-      // If incomming connections are requested make sure to post already
+      // If incoming connections are requested make sure to post already
       // accepted connections.
       if ((msg->data & (1 << kInEvent)) != 0) {
         if (listen_socket->CanAccept()) {
diff --git a/runtime/bin/extensions.cc b/runtime/bin/extensions.cc
index 71eaeac..d28d1e1 100644
--- a/runtime/bin/extensions.cc
+++ b/runtime/bin/extensions.cc
@@ -21,7 +21,7 @@
   char* library_path = strdup(extension_url);
 
   if (library_path == NULL) {
-    return Dart_Error("Out of memory in LoadExtension");
+    return Dart_NewApiError("Out of memory in LoadExtension");
   }
 
   // Extract the path and the extension name from the url.
@@ -32,7 +32,7 @@
   void* library_handle = LoadExtensionLibrary(library_path, extension_name);
   if (library_handle == NULL) {
     free(library_path);
-    return Dart_Error("cannot find extension library");
+    return Dart_NewApiError("cannot find extension library");
   }
 
   const char* strings[] = { extension_name, "_Init", NULL };
@@ -44,7 +44,7 @@
   free(library_path);
 
   if (fn == NULL) {
-    return Dart_Error("cannot find initialization function in extension");
+    return Dart_NewApiError("cannot find initialization function in extension");
   }
   return (*fn)(parent_library);
 }
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 9f70743..2da2778 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -282,11 +282,11 @@
                                                    Dart_Handle library,
                                                    Dart_Handle url) {
   if (!Dart_IsLibrary(library)) {
-    return Dart_Error("not a library");
+    return Dart_NewApiError("not a library");
   }
   Dart_Handle library_url = Dart_LibraryUrl(library);
   if (Dart_IsError(library_url)) {
-    return Dart_Error("accessing library url failed");
+    return Dart_NewApiError("accessing library url failed");
   }
   const char* library_url_string = DartUtils::GetStringValue(library_url);
   const char* mapped_library_url_string = DartUtils::MapLibraryUrl(
@@ -297,7 +297,7 @@
   }
 
   if (!Dart_IsString(url)) {
-    return Dart_Error("url is not a string");
+    return Dart_NewApiError("url is not a string");
   }
   const char* url_string = DartUtils::GetStringValue(url);
   const char* mapped_url_string = DartUtils::MapLibraryUrl(url_mapping,
@@ -322,7 +322,7 @@
       return Builtin::LoadAndCheckLibrary(builtinId);
     }
     ASSERT(tag == Dart_kSourceTag);
-    return Dart_Error("Unable to part '%s' ", url_string);
+    return DartUtils::NewError("Unable to part '%s' ", url_string);
   }
 
   if (libraryBuiltinId != Builtin::kInvalidLibrary) {
@@ -332,7 +332,7 @@
           library, url, Builtin::PartSource(libraryBuiltinId, url_string));
     }
     ASSERT(tag == Dart_kImportTag);
-    return Dart_Error("Unable to import '%s' ", url_string);
+    return DartUtils::NewError("Unable to import '%s' ", url_string);
   }
 
   Dart_Handle resolved_url = url;
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 9fc01ec..76c0062 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -360,8 +360,7 @@
 }
 
 
-static Dart_Handle SetupRuntimeOptions(CommandLineOptions* options,
-                                       const char* script_name) {
+static Dart_Handle CreateRuntimeOptions(CommandLineOptions* options) {
   int options_count = options->count();
   Dart_Handle dart_arguments = Dart_NewList(options_count);
   if (Dart_IsError(dart_arguments)) {
@@ -378,6 +377,15 @@
       return result;
     }
   }
+  return dart_arguments;
+}
+
+
+static Dart_Handle SetupRuntimeOptions(CommandLineOptions* options) {
+  Dart_Handle dart_arguments = CreateRuntimeOptions(options);
+  if (Dart_IsError(dart_arguments)) {
+    return dart_arguments;
+  }
   Dart_Handle io_lib_url = DartUtils::NewString("dart:io");
   if (Dart_IsError(io_lib_url)) {
     return io_lib_url;
@@ -827,8 +835,7 @@
     }
 
     // Create a dart options object that can be accessed from dart code.
-    Dart_Handle options_result =
-        SetupRuntimeOptions(&dart_options, script_name);
+    Dart_Handle options_result = SetupRuntimeOptions(&dart_options);
     if (Dart_IsError(options_result)) {
       return DartErrorExit(options_result);
     }
@@ -856,7 +863,17 @@
       }
     } else {
       // Lookup and invoke the top level main function.
-      result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL);
+      Dart_Handle main_args[1];
+      main_args[0] = CreateRuntimeOptions(&dart_options);
+      result = Dart_Invoke(library, DartUtils::NewString("main"), 1, main_args);
+      // TODO(iposva): Return a special error type for mismatched argument
+      // counts from Dart_Invoke to avoid the string comparison.
+      const char* expected_error = "Dart_Invoke: wrong argument count for "
+          "function 'main': 1 passed, 0 expected.";
+      if (Dart_IsError(result) &&
+          strcmp(expected_error, Dart_GetError(result)) == 0) {
+        result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL);
+      }
       if (Dart_IsError(result)) {
         return DartErrorExit(result);
       }
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 2a45192..320d3da 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -290,10 +290,10 @@
                                          Dart_Handle library,
                                          Dart_Handle url) {
   if (!Dart_IsLibrary(library)) {
-    return Dart_Error("not a library");
+    return Dart_NewApiError("not a library");
   }
   if (!Dart_IsString(url)) {
-    return Dart_Error("url is not a string");
+    return Dart_NewApiError("url is not a string");
   }
   const char* url_string = NULL;
   Dart_Handle result = Dart_StringToCString(url, &url_string);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index bcd3474..5aa10cb 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -284,10 +284,9 @@
  *
  * Requires there to be a current isolate.
  *
- * \param format A printf style format specifier used to construct the
- *   error message.
+ * \param error the error message.
  */
-DART_EXPORT Dart_Handle Dart_NewApiError(const char* format, ...);
+DART_EXPORT Dart_Handle Dart_NewApiError(const char* error);
 
 /**
  * Produces a new unhandled exception error handle.
@@ -300,7 +299,7 @@
 
 /* Deprecated. */
 /* TODO(turnidge): Remove all uses and delete. */
-DART_EXPORT Dart_Handle Dart_Error(const char* format, ...);
+DART_EXPORT Dart_Handle Dart_Error(const char* error);
 
 /**
  * Propagates an error.
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index ea95306..d2331c3 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -583,15 +583,16 @@
 
   // Set.
 
-  void add(E element) {
+  bool add(E element) {
     int hashCode = _hashCode(element);
     int index = hashCode & (_buckets.length - 1);
     HashSetEntry entry = _buckets[index];
     while (entry != null) {
-      if (_equals(entry.key, element)) return;
+      if (_equals(entry.key, element)) return false;
       entry = entry.next;
     }
     _addEntry(element, hashCode, index);
+    return true;
   }
 
   void addAll(Iterable<E> objects) {
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 07029a2..dc6808b 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -839,13 +839,15 @@
   ASSERT(type.IsFinalized());
   ASSERT(type.HasResolvedTypeClass());
   const Class& cls = Class::Handle(type.type_class());
-  if (cls.IsDynamicClass() || cls.IsVoidClass()) {
+  ASSERT(!cls.IsNull());
+  if (cls.IsDynamicClass() ||
+      cls.IsVoidClass() ||
+      (cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass())) {
     Exceptions::ThrowArgumentError(type);
     UNREACHABLE();
   }
-  const AbstractType& stripped_type = AbstractType::Handle(cls.RareType());
   return CreateClassMirror(cls,
-                           stripped_type,
+                           AbstractType::Handle(cls.DeclarationType()),
                            Bool::True(),  // is_declaration
                            Object::null_instance());
 }
@@ -967,6 +969,10 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(!type.IsMalformed());
   ASSERT(type.IsFinalized());
+  if (!type.HasResolvedTypeClass()) {
+    Exceptions::ThrowArgumentError(type);
+    UNREACHABLE();
+  }
   const Class& cls = Class::Handle(type.type_class());
   const AbstractType& super_type = AbstractType::Handle(cls.super_type());
   ASSERT(super_type.IsNull() || super_type.IsFinalized());
@@ -977,6 +983,10 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(!type.IsMalformed());
   ASSERT(type.IsFinalized());
+  if (!type.HasResolvedTypeClass()) {
+    Exceptions::ThrowArgumentError(type);
+    UNREACHABLE();
+  }
   const Class& cls = Class::Handle(type.type_class());
   AbstractType& super_type = AbstractType::Handle(cls.super_type());
   AbstractType& result = AbstractType::Handle(super_type.raw());
@@ -1001,22 +1011,118 @@
 
 
 DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
-  const Class& klass = Class::Handle(ref.GetClassReferent());
-
-  const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
+  ASSERT(!type.IsMalformed());
+  ASSERT(type.IsFinalized());
+  if (!type.HasResolvedTypeClass()) {
+    Exceptions::ThrowArgumentError(type);
+    UNREACHABLE();
+  }
+  const Class& cls = Class::Handle(type.type_class());
+  const Error& error = Error::Handle(cls.EnsureIsFinalized(isolate));
   if (!error.IsNull()) {
     ThrowInvokeError(error);
   }
 
-  return klass.interfaces();
+  return cls.interfaces();
+}
+
+DEFINE_NATIVE_ENTRY(ClassMirror_interfaces_instantiated, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
+  ASSERT(!type.IsMalformed());
+  ASSERT(type.IsFinalized());
+  if (!type.HasResolvedTypeClass()) {
+    Exceptions::ThrowArgumentError(type);
+    UNREACHABLE();
+  }
+  const Class& cls = Class::Handle(type.type_class());
+  const Error& error = Error::Handle(cls.EnsureIsFinalized(isolate));
+  if (!error.IsNull()) {
+    ThrowInvokeError(error);
+  }
+
+  AbstractTypeArguments& type_args =
+      AbstractTypeArguments::Handle(type.arguments());
+  Error& bound_error = Error::Handle();
+
+  Array& interfaces = Array::Handle(cls.interfaces());
+  Array& interfaces_inst = Array::Handle(Array::New(interfaces.Length()));
+  AbstractType& interface = AbstractType::Handle();
+
+  for (int i = 0; i < interfaces.Length(); i++) {
+    interface ^= interfaces.At(i);
+    ASSERT(interface.IsType());
+    if (!interface.IsInstantiated()) {
+      bound_error ^= Object::null();
+      interface ^= interface.InstantiateFrom(type_args, &bound_error);
+      if (!bound_error.IsNull()) {
+        ThrowInvokeError(bound_error);
+        UNREACHABLE();
+      }
+      interface ^= interface.Canonicalize();
+      ASSERT(interface.IsType());
+    }
+    interfaces_inst.SetAt(i, interface);
+  }
+
+  return interfaces_inst.raw();
 }
 
 
 DEFINE_NATIVE_ENTRY(ClassMirror_mixin, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
-  const Class& klass = Class::Handle(ref.GetClassReferent());
-  return klass.mixin();
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
+  ASSERT(!type.IsMalformed());
+  ASSERT(type.IsFinalized());
+  if (!type.HasResolvedTypeClass()) {
+    Exceptions::ThrowArgumentError(type);
+    UNREACHABLE();
+  }
+  const Class& cls = Class::Handle(type.type_class());
+  const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+  ASSERT(mixin_type.IsNull() || mixin_type.IsFinalized());
+  return mixin_type.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(ClassMirror_mixin_instantiated, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType,
+                               instantiator,
+                               arguments->NativeArgAt(1));
+  ASSERT(!type.IsMalformed());
+  ASSERT(type.IsFinalized());
+  if (!type.HasResolvedTypeClass()) {
+    Exceptions::ThrowArgumentError(type);
+    UNREACHABLE();
+  }
+  const Class& cls = Class::Handle(type.type_class());
+  const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+  if (mixin_type.IsNull()) {
+    return mixin_type.raw();
+  }
+  ASSERT(mixin_type.IsFinalized());
+
+  ASSERT(!instantiator.IsMalformed());
+  ASSERT(instantiator.IsFinalized());
+
+  AbstractType& result = AbstractType::Handle(mixin_type.raw());
+
+  ASSERT(mixin_type.IsType());
+  if (!mixin_type.IsInstantiated()) {
+    AbstractTypeArguments& type_args =
+        AbstractTypeArguments::Handle(instantiator.arguments());
+    Error& bound_error = Error::Handle();
+    result ^= mixin_type.InstantiateFrom(type_args, &bound_error);
+    if (!bound_error.IsNull()) {
+      ThrowInvokeError(bound_error);
+      UNREACHABLE();
+    }
+    result ^= result.Canonicalize();
+    ASSERT(result.IsType());
+  }
+
+  ASSERT(result.IsFinalized());
+  return result.raw();
 }
 
 
@@ -1121,7 +1227,7 @@
       // TODO(12478): Should not need to filter out dynamic.
       if (!klass.IsCanonicalSignatureClass() &&
           !klass.IsDynamicClass()) {
-        type = klass.RareType();
+        type = klass.DeclarationType();
         member_mirror = CreateClassMirror(klass,
                                           type,
                                           Bool::True(),  // is_declaration
@@ -1196,7 +1302,7 @@
 DEFINE_NATIVE_ENTRY(TypeVariableMirror_owner, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
   const Class& owner = Class::Handle(param.parameterized_class());
-  const AbstractType& type = AbstractType::Handle(owner.RareType());
+  const AbstractType& type = AbstractType::Handle(owner.DeclarationType());
   return CreateClassMirror(owner,
                            type,
                            Bool::True(),  // is_declaration
@@ -1570,6 +1676,12 @@
   ASSERT(!type.IsNull());
   AbstractTypeArguments& type_arguments =
       AbstractTypeArguments::Handle(type.arguments());
+  if (!type.IsInstantiated()) {
+    // Must have been a declaration type.
+    AbstractType& rare_type = AbstractType::Handle(klass.RareType());
+    ASSERT(rare_type.IsInstantiated());
+    type_arguments = rare_type.arguments();
+  }
 
   Class& redirected_klass = Class::Handle(klass.raw());
   Function& redirected_constructor = Function::Handle(lookup_constructor.raw());
@@ -1786,7 +1898,7 @@
     return CreateLibraryMirror(Library::Handle(owner.library()));
   }
 
-  AbstractType& type = AbstractType::Handle(owner.RareType());
+  AbstractType& type = AbstractType::Handle(owner.DeclarationType());
   return CreateClassMirror(owner, type, Bool::True(), Object::null_instance());
 }
 
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index f0d5aa9..26688f0 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -269,7 +269,7 @@
     if (_type == null) {
       // Note it not safe to use reflectee.runtimeType because runtimeType may
       // be overridden.
-      _type = _Mirrors._reflectType(_computeType(reflectee));
+      _type = reflectType(_computeType(reflectee));
     }
     return _type;
   }
@@ -420,18 +420,21 @@
 class _LocalClassMirrorImpl extends _LocalObjectMirrorImpl
     implements ClassMirror {
   _LocalClassMirrorImpl(reflectee,
-                        this._reflectedType,
+                        reflectedType,
                         String simpleName,
                         this._isGeneric,
                         this._isMixinTypedef,
                         this._isGenericDeclaration)
       : this._simpleName = _s(simpleName),
+        this._reflectedType = reflectedType,
+        this._instantiator = reflectedType,
         super(reflectee);
 
   final Type _reflectedType;
   final bool _isGeneric;
   final bool _isMixinTypedef;
   final bool _isGenericDeclaration;
+  Type _instantiator;
 
   TypeMirror _instantiateInContextOf(declaration) => this;
 
@@ -492,7 +495,8 @@
         // Object has no superclass.
         return null;
       }
-      _trueSuperclassField = _Mirrors._reflectType(supertype);
+      _trueSuperclassField = reflectType(supertype);
+      _trueSuperclassField._instantiator = _instantiator;
     }
     return _trueSuperclassField;
   }
@@ -503,8 +507,11 @@
   var _superinterfaces;
   List<ClassMirror> get superinterfaces {
     if (_superinterfaces == null) {
-      _superinterfaces = _interfaces(_reflectee)
-          .map((i) => _Mirrors._reflectType(i)).toList(growable:false);
+      _superinterfaces = isOriginalDeclaration
+          ? _nativeInterfaces(_reflectedType)
+          : _nativeInterfacesInstantiated(_reflectedType);
+      _superinterfaces = _superinterfaces
+          .map((i) => reflectType(i)).toList(growable:false);
     }
     return _superinterfaces;
   }
@@ -512,7 +519,7 @@
   get _mixinApplicationName {
     var mixins = new List<ClassMirror>();
     var klass = this;
-    while (_computeMixin(klass._reflectee) != null) {
+    while (_nativeMixin(klass._reflectedType) != null) {
       mixins.add(klass.mixin);
       klass = klass.superclass;
     }
@@ -526,14 +533,19 @@
   ClassMirror get mixin {
     if (_mixin == null) {
       if (_isMixinTypedef) {
-        _mixin = _trueSuperclass.mixin;
+        Type mixinType = isOriginalDeclaration
+            ? _nativeMixin(_trueSuperclass._reflectedType)
+            : _nativeMixinInstantiated(_trueSuperclass._reflectedType, _instantiator);
+        _mixin = reflectType(mixinType);
       } else {
-        var mixinType = _computeMixin(_reflectee);
+        Type mixinType = isOriginalDeclaration
+            ? _nativeMixin(_reflectedType)
+            : _nativeMixinInstantiated(_reflectedType, _instantiator);
         if (mixinType == null) {
           // The reflectee is not a mixin application.
           _mixin = this;
         } else {
-          _mixin = _Mirrors._reflectType(mixinType);
+          _mixin = reflectType(mixinType);
         }
       }
     }
@@ -709,12 +721,18 @@
   static _supertypeInstantiated(reflectedType)
       native "ClassMirror_supertype_instantiated";
 
-  static _interfaces(reflectee)
+  static _nativeInterfaces(reflectedType)
       native "ClassMirror_interfaces";
 
-  static _computeMixin(reflectee)
+  static _nativeInterfacesInstantiated(reflectedType)
+      native "ClassMirror_interfaces_instantiated";
+
+  static _nativeMixin(reflectedType)
       native "ClassMirror_mixin";
 
+  static _nativeMixinInstantiated(reflectedType, instantiator)
+      native "ClassMirror_mixin_instantiated";
+
   _computeMembers(reflectee)
       native "ClassMirror_members";
 
@@ -745,6 +763,8 @@
   _LocalFunctionTypeMirrorImpl(reflectee, reflectedType)
       : super(reflectee, reflectedType, null, false, false, false);
 
+  bool get _isAnonymousMixinApplication => false;
+
   // FunctionTypeMirrors have a simpleName generated from their signature.
   Symbol _simpleName = null;
   Symbol get simpleName {
@@ -766,7 +786,7 @@
   TypeMirror get returnType {
     if (_returnType == null) {
       _returnType =
-          _Mirrors._reflectType(_FunctionTypeMirror_return_type(_reflectee));
+          reflectType(_FunctionTypeMirror_return_type(_reflectee));
     }
     return _returnType;
   }
@@ -852,8 +872,7 @@
   TypeMirror _upperBound = null;
   TypeMirror get upperBound {
     if (_upperBound == null) {
-      _upperBound =
-          _Mirrors._reflectType(_TypeVariableMirror_upper_bound(_reflectee));
+      _upperBound = reflectType(_TypeVariableMirror_upper_bound(_reflectee));
     }
     return _upperBound;
   }
@@ -869,6 +888,13 @@
 
   String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
 
+  operator ==(other) {
+    return other is TypeVariableMirror 
+        && simpleName == other.simpleName
+        && owner == other.owner;
+  }
+  int get hashCode => simpleName.hashCode;
+
   static DeclarationMirror _TypeVariableMirror_owner(reflectee)
       native "TypeVariableMirror_owner";
 
@@ -885,10 +911,9 @@
     if (instantiator is! ClassMirror) throw "UNREACHABLE";
     if (instantiator.isOriginalDeclaration) return this;
 
-    return _Mirrors._reflectType(
-        _TypeVariableMirror_instantiate_from(
-            _reflectee,
-            instantiator._reflectedType));
+    return reflectType(
+        _TypeVariableMirror_instantiate_from(_reflectee,
+                                             instantiator._reflectedType));
   }
 }
 
@@ -975,6 +1000,14 @@
     return _members;
   }
 
+  Map<Symbol, ClassMirror> _types;
+  Map<Symbol, TypeMirror> get types {
+    if (_types == null) {
+      _types = _filterMap(members, (key, value) => (value is TypeMirror));
+    }
+    return _types;
+  }
+
   Map<Symbol, ClassMirror> _classes;
   Map<Symbol, ClassMirror> get classes {
     if (_classes == null) {
@@ -1101,8 +1134,7 @@
       if (isConstructor) {
         _returnType = owner;
       } else {
-        _returnType =
-            _Mirrors._reflectType(_MethodMirror_return_type(_reflectee));
+        _returnType = reflectType(_MethodMirror_return_type(_reflectee));
       }
       _returnType = _returnType._instantiateInContextOf(owner);
     }
@@ -1198,7 +1230,7 @@
   TypeMirror _type;
   TypeMirror get type {
     if (_type == null) {
-       _type = _Mirrors._reflectType(_VariableMirror_type(_reflectee));
+       _type = reflectType(_VariableMirror_type(_reflectee));
        _type = _type._instantiateInContextOf(owner);
     }
     return _type;
@@ -1255,8 +1287,7 @@
   TypeMirror _type = null;
   TypeMirror get type {
     if (_type == null) {
-      _type =
-          _Mirrors._reflectType(_ParameterMirror_type(_reflectee, _position));
+      _type = reflectType(_ParameterMirror_type(_reflectee, _position));
       _type = _type._instantiateInContextOf(owner);
     }
     return _type;
@@ -1347,7 +1378,7 @@
       native "Mirrors_makeLocalTypeMirror";
 
   static Expando<ClassMirror> _declarationCache = new Expando("ClassMirror");
-  static Expando<ClassMirror> _instanitationCache = new Expando("TypeMirror");
+  static Expando<TypeMirror> _instanitationCache = new Expando("TypeMirror");
 
   static ClassMirror reflectClass(Type key) {
     var classMirror = _declarationCache[key];
@@ -1361,7 +1392,7 @@
     return classMirror;
   }
 
-  static TypeMirror _reflectType(Type key) {
+  static TypeMirror reflectType(Type key) {
     var typeMirror = _instanitationCache[key];
     if (typeMirror == null) {
       typeMirror = makeLocalTypeMirror(key);
diff --git a/runtime/lib/mirrors_patch.dart b/runtime/lib/mirrors_patch.dart
index 93d1876..364b0ab 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/runtime/lib/mirrors_patch.dart
@@ -41,6 +41,10 @@
   return _Mirrors.reflectClass(key);
 }
 
+patch TypeMirror reflectType(Type key) {
+  return _Mirrors.reflectType(key);
+}
+
 patch class MirrorSystem {
   /* patch */ static String getName(Symbol symbol) {
     String string = _symbol_dev.Symbol.getName(symbol);
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index 8f79577..1576139 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -171,6 +171,19 @@
   // Check that the classes map is complete.
   keys = lib_mirror.classes.keys.map(MirrorSystem.getName).toList();
   sort(keys);
+  print(keys);
+  Expect.equals('['
+                'GenericClass, '
+                'MyClass, '
+                'MyException, '
+                'MyInterface, '
+                'MySuperClass]',
+                '$keys');
+
+  // Check that the types map is complete.
+  keys = lib_mirror.types.keys.map(MirrorSystem.getName).toList();
+  sort(keys);
+  print(keys);
   Expect.equals('['
                 'FuncType, '
                 'GenericClass, '
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index aaa42f6..f42e26d 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -100,7 +100,12 @@
   ASSERT(CPUInfoContainsString("ARMv7"));  // Implements ARMv7.
   ASSERT(CPUInfoContainsString("vfp"));  // Has floating point unit.
   // Has integer division.
-  integer_division_supported_ = CPUInfoContainsString("idiva");
+  if (CPUInfoContainsString("QCT APQ8064")) {
+    // Special case for Qualcomm Krait CPUs in Nexus 4 and 7.
+    integer_division_supported_ = true;
+  } else {
+    integer_division_supported_ = CPUInfoContainsString("idiva");
+  }
   neon_supported_ = CPUInfoContainsString("neon");
 #endif  // defined(USING_SIMULATOR)
 #if defined(DEBUG)
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index c6ab494..a2e629c 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -166,8 +166,8 @@
       isolate, GetLibrarySource(lib, uri, false));
   const String& lib_uri = String::Handle(isolate, lib.url());
   if (part_source.IsNull()) {
-    return Dart_NewApiError("Unable to read part file '%s' of library '%s'",
-                            uri.ToCString(), lib_uri.ToCString());
+    return Api::NewError("Unable to read part file '%s' of library '%s'",
+                         uri.ToCString(), lib_uri.ToCString());
   }
 
   // Prepend the library URI to form a unique script URI for the part.
@@ -190,10 +190,10 @@
                                               Dart_Handle uri) {
   Isolate* isolate = Isolate::Current();
   if (!Dart_IsLibrary(library)) {
-    return Dart_NewApiError("not a library");
+    return Api::NewError("not a library");
   }
   if (!Dart_IsString(uri)) {
-    return Dart_NewApiError("uri is not a string");
+    return Api::NewError("uri is not a string");
   }
   if (tag == Dart_kCanonicalizeUrl) {
     // In the boot strap loader we do not try and do any canonicalization.
@@ -207,8 +207,8 @@
     // We have precreated all the bootstrap library objects hence
     // we do not expect to be called back with the tag set to kImportTag.
     // The bootstrap process explicitly loads all the libraries one by one.
-    return Dart_NewApiError("Invalid import of '%s' in a bootstrap library",
-                            uri_str.ToCString());
+    return Api::NewError("Invalid import of '%s' in a bootstrap library",
+                         uri_str.ToCString());
   }
   ASSERT(tag == Dart_kSourceTag);
   const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index acf46d3..104756a 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -269,7 +269,9 @@
   V(ClassMirror_supertype, 1)                                                  \
   V(ClassMirror_supertype_instantiated, 1)                                     \
   V(ClassMirror_interfaces, 1)                                                 \
+  V(ClassMirror_interfaces_instantiated, 1)                                    \
   V(ClassMirror_mixin, 1)                                                      \
+  V(ClassMirror_mixin_instantiated, 2)                                         \
   V(ClassMirror_members, 2)                                                    \
   V(ClassMirror_constructors, 2)                                               \
   V(LibraryMirror_members, 2)                                                  \
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 52c346b..46a159c 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -387,46 +387,19 @@
 
 // Deprecated.
 // TODO(turnidge): Remove all uses and delete.
-DART_EXPORT Dart_Handle Dart_Error(const char* format, ...) {
-  Isolate* isolate = Isolate::Current();
-  DARTSCOPE(isolate);
-  CHECK_CALLBACK_STATE(isolate);
-
-  va_list args;
-  va_start(args, format);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
-  va_end(args);
-
-  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
-  va_list args2;
-  va_start(args2, format);
-  OS::VSNPrint(buffer, (len + 1), format, args2);
-  va_end(args2);
-
-  const String& message = String::Handle(isolate, String::New(buffer));
-  return Api::NewHandle(isolate, ApiError::New(message));
+DART_EXPORT Dart_Handle Dart_Error(const char* error) {
+  return Dart_NewApiError(error);
 }
 
 
 // TODO(turnidge): This clones Api::NewError.  I need to use va_copy to
 // fix this but not sure if it available on all of our builds.
-DART_EXPORT Dart_Handle Dart_NewApiError(const char* format, ...) {
+DART_EXPORT Dart_Handle Dart_NewApiError(const char* error) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   CHECK_CALLBACK_STATE(isolate);
 
-  va_list args;
-  va_start(args, format);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
-  va_end(args);
-
-  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
-  va_list args2;
-  va_start(args2, format);
-  OS::VSNPrint(buffer, (len + 1), format, args2);
-  va_end(args2);
-
-  const String& message = String::Handle(isolate, String::New(buffer));
+  const String& message = String::Handle(isolate, String::New(error));
   return Api::NewHandle(isolate, ApiError::New(message));
 }
 
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 53da807..3524d71 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -67,7 +67,7 @@
   const String& fatal_message = String::Handle(String::New("FatalError"));
 
   Dart_Handle not_error = NewString("NotError");
-  Dart_Handle api_error = Dart_NewApiError("Api%s", "Error");
+  Dart_Handle api_error = Api::NewError("Api%s", "Error");
   Dart_Handle exception_error =
       Dart_NewUnhandledExceptionError(NewString("ExceptionError"));
   Dart_Handle compile_error =
@@ -168,7 +168,7 @@
 
 
 TEST_CASE(Dart_Error) {
-  Dart_Handle error = Dart_Error("An %s", "error");
+  Dart_Handle error = Api::NewError("An %s", "error");
   EXPECT(Dart_IsError(error));
   EXPECT_STREQ("An error", Dart_GetError(error));
 }
@@ -3399,7 +3399,7 @@
   // TODO(12455) Need better validation.
   // We expect the test script to fail finalization with the error below:
   EXPECT(Dart_IsError(result));
-  Dart_Handle expected_error = Dart_Error(
+  Dart_Handle expected_error = DartUtils::NewError(
       "'dart:test-lib': Error: line 1 pos 36: "
       "class 'NativeFields' is trying to extend a native fields class, "
       "but library '%s' has no native resolvers",
@@ -3830,7 +3830,7 @@
   Dart_Handle args[1];
   args[0] = Dart_NewInteger(11);
   Dart_Handle bad_args[1];
-  bad_args[0] = Dart_Error("myerror");
+  bad_args[0] = Dart_NewApiError("myerror");
 
   // Invoke the unnamed constructor.
   Dart_Handle result = Dart_New(type, Dart_Null(), 0, NULL);
@@ -3947,7 +3947,7 @@
   EXPECT(Dart_IsNull(result));
 
   // Pass an error class object.  Error is passed through.
-  result = Dart_New(Dart_Error("myerror"), NewString("named"), 1, args);
+  result = Dart_New(Dart_NewApiError("myerror"), NewString("named"), 1, args);
   EXPECT_ERROR(result, "myerror");
 
   // Pass a bad class object.
@@ -4621,7 +4621,7 @@
       "}";
   Dart_Handle url = NewString(TestCase::url());
   Dart_Handle source = NewString(kScriptChars);
-  Dart_Handle error = Dart_Error("incoming error");
+  Dart_Handle error = Dart_NewApiError("incoming error");
   Dart_Handle result;
 
   result = Dart_SetLibraryTagHandler(library_handler);
@@ -4794,7 +4794,7 @@
       "Dart_LookupLibrary expects argument 'url' to be of type String.",
       Dart_GetError(result));
 
-  result = Dart_LookupLibrary(Dart_Error("incoming error"));
+  result = Dart_LookupLibrary(Dart_NewApiError("incoming error"));
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ("incoming error", Dart_GetError(result));
 
@@ -4812,7 +4812,7 @@
   Dart_Handle url = NewString("library1_url");
   Dart_Handle source = NewString(kLibrary1Chars);
   Dart_Handle lib = Dart_LoadLibrary(url, source);
-  Dart_Handle error = Dart_Error("incoming error");
+  Dart_Handle error = Dart_NewApiError("incoming error");
   EXPECT_VALID(lib);
 
   Dart_Handle result = Dart_LibraryName(Dart_Null());
@@ -4845,7 +4845,7 @@
   Dart_Handle url = NewString("library1_url");
   Dart_Handle source = NewString(kLibrary1Chars);
   Dart_Handle lib = Dart_LoadLibrary(url, source);
-  Dart_Handle error = Dart_Error("incoming error");
+  Dart_Handle error = Dart_NewApiError("incoming error");
   EXPECT_VALID(lib);
 
   Dart_Handle result = Dart_LibraryUrl(Dart_Null());
@@ -4984,7 +4984,7 @@
       "library library1_name;";
   const char* kLibrary2Chars =
       "library library2_name;";
-  Dart_Handle error = Dart_Error("incoming error");
+  Dart_Handle error = Dart_NewApiError("incoming error");
   Dart_Handle result;
 
   Dart_Handle url = NewString("library1_url");
@@ -5078,7 +5078,7 @@
 TEST_CASE(LoadLibrary) {
   const char* kLibrary1Chars =
       "library library1_name;";
-  Dart_Handle error = Dart_Error("incoming error");
+  Dart_Handle error = Dart_NewApiError("incoming error");
   Dart_Handle result;
 
   Dart_Handle url = NewString("library1_url");
@@ -5146,7 +5146,7 @@
       "part of library1_name;\n// Something innocuous";
   const char* kBadSourceChars =
       ")";
-  Dart_Handle error = Dart_Error("incoming error");
+  Dart_Handle error = Dart_NewApiError("incoming error");
   Dart_Handle result;
 
   // Load up a library.
@@ -5525,7 +5525,7 @@
       "  static bar() native \"SomeNativeFunction2\";"
       "  static baz() native \"SomeNativeFunction3\";"
       "}";
-  Dart_Handle error = Dart_Error("incoming error");
+  Dart_Handle error = Dart_NewApiError("incoming error");
   Dart_Handle result;
 
   // Load a test script.
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 016191d..6c60c21 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -3223,27 +3223,6 @@
 }
 
 
-static bool MayBeBoxableNumber(intptr_t cid) {
-  return (cid == kDynamicCid) ||
-         (cid == kMintCid) ||
-         (cid == kBigintCid) ||
-         (cid == kDoubleCid);
-}
-
-
-// Check if number check is not needed.
-void FlowGraphOptimizer::VisitStrictCompare(StrictCompareInstr* instr) {
-  if (!instr->needs_number_check()) return;
-
-  // If one of the input is not a boxable number (Mint, Double, Bigint), no
-  // need for number checks.
-  if (!MayBeBoxableNumber(instr->left()->Type()->ToCid()) ||
-      !MayBeBoxableNumber(instr->right()->Type()->ToCid()))  {
-    instr->set_needs_number_check(false);
-  }
-}
-
-
 // Range analysis for smi values.
 class RangeAnalysis : public ValueObject {
  public:
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 08233a1..79d6fe3 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -58,7 +58,6 @@
   virtual void VisitInstanceCall(InstanceCallInstr* instr);
   virtual void VisitEqualityCompare(EqualityCompareInstr* instr);
   virtual void VisitBranch(BranchInstr* instr);
-  virtual void VisitStrictCompare(StrictCompareInstr* instr);
 
   void InsertBefore(Instruction* next,
                     Instruction* instr,
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 80817b5..d0587ff 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -73,7 +73,7 @@
 
 void FlowGraphPrinter::PrintOneInstruction(Instruction* instr,
                                            bool print_locations) {
-  char str[1000];
+  char str[4000];
   BufferFormatter f(str, sizeof(str));
   instr->PrintTo(&f);
   if (FLAG_print_environments && (instr->env() != NULL)) {
@@ -97,8 +97,8 @@
                                       const String& dst_name,
                                       bool eliminated) {
     const char* compile_type_name = "unknown";
-    if (value != NULL) {
-      compile_type_name = value->Type()->ToCString();
+    if (value != NULL && value->reaching_type_ != NULL) {
+      compile_type_name = value->reaching_type_->ToCString();
     }
     OS::Print("%s type check: compile type %s is %s specific than "
               "type '%s' of '%s'.\n",
@@ -232,7 +232,7 @@
 void Value::PrintTo(BufferFormatter* f) const {
   PrintUse(f, *definition());
   if ((reaching_type_ != NULL) &&
-      (reaching_type_ != definition()->Type())) {
+      (reaching_type_ != definition()->type_)) {
     f->Print(" ");
     reaching_type_->PrintTo(f);
   }
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 2b35c8d..fdbaa09 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -1516,33 +1516,95 @@
 }
 
 
+Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) {
+  Definition* defn = value()->definition();
+  if (defn->IsComparison() &&
+      (value()->Type()->ToCid() == kBoolCid) &&
+      defn->HasOnlyUse(value())) {
+    defn->AsComparison()->NegateComparison();
+    return defn;
+  }
+  return this;
+}
+
+
+static bool MayBeBoxableNumber(intptr_t cid) {
+  return (cid == kDynamicCid) ||
+         (cid == kMintCid) ||
+         (cid == kBigintCid) ||
+         (cid == kDoubleCid);
+}
+
+
+static bool MaybeNumber(CompileType* type) {
+  ASSERT(Type::Handle(Type::Number()).IsMoreSpecificThan(
+         Type::Handle(Type::Number()), NULL));
+  return type->ToAbstractType()->IsDynamicType()
+      || type->ToAbstractType()->IsTypeParameter()
+      || type->IsMoreSpecificThan(Type::Handle(Type::Number()));
+}
+
+
+// Returns a replacement for a strict comparison and signals if the result has
+// to be negated.
 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare,
                                              bool* negated) {
+  // Use propagated cid and type information to eliminate number checks.
+  // If one of the inputs is not a boxable number (Mint, Double, Bigint), or
+  // is not a subtype of num, no need for number checks.
+  if (compare->needs_number_check()) {
+    if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) ||
+        !MayBeBoxableNumber(compare->right()->Type()->ToCid()))  {
+      compare->set_needs_number_check(false);
+    } else if (!MaybeNumber(compare->left()->Type()) ||
+               !MaybeNumber(compare->right()->Type())) {
+      compare->set_needs_number_check(false);
+    }
+  }
+
   *negated = false;
-  if (!compare->right()->BindsToConstant()) {
+  Object& constant = Object::Handle();
+  Value* other = NULL;
+  if (compare->right()->BindsToConstant()) {
+    constant = compare->right()->BoundConstant().raw();
+    other = compare->left();
+  } else if (compare->left()->BindsToConstant()) {
+    constant = compare->left()->BoundConstant().raw();
+    other = compare->right();
+  } else {
     return compare;
   }
-  const Object& right_constant = compare->right()->BoundConstant();
-  Definition* left_defn = compare->left()->definition();
 
-  // TODO(fschneider): Handle other cases: e === false and e !== true/false.
-  // Handles e === true.
-  if ((compare->kind() == Token::kEQ_STRICT) &&
-      (right_constant.raw() == Bool::True().raw()) &&
-      (compare->left()->Type()->ToCid() == kBoolCid)) {
-    // Return left subexpression as the replacement for this instruction.
-    return left_defn;
+  Definition* other_defn = other->definition();
+  Token::Kind kind = compare->kind();
+  // Handle e === true.
+  if ((kind == Token::kEQ_STRICT) &&
+      (constant.raw() == Bool::True().raw()) &&
+      (other->Type()->ToCid() == kBoolCid)) {
+    return other_defn;
   }
-  // x = (a === b);  y = x !== true; -> y = a !== b.
-  // In order to merge two strict compares, 'left_strict' must have only one
-  // use. Do not check left's cid as it is required to be a strict compare.
-  StrictCompareInstr* left_strict = left_defn->AsStrictCompare();
-  if ((compare->kind() == Token::kNE_STRICT) &&
-      (right_constant.raw() == Bool::True().raw()) &&
-      (left_strict != NULL) &&
-      (left_strict->HasOnlyUse(compare->left()))) {
+  // Handle e !== false.
+  if ((kind == Token::kNE_STRICT) &&
+      (constant.raw() == Bool::False().raw()) &&
+      (other->Type()->ToCid() == kBoolCid)) {
+    return other_defn;
+  }
+  // Handle e !== true
+  if ((kind == Token::kNE_STRICT) &&
+      (constant.raw() == Bool::True().raw()) &&
+      other_defn->IsComparison() &&
+      (other->Type()->ToCid() == kBoolCid) &&
+      other_defn->HasOnlyUse(other)) {
     *negated = true;
-    return left_strict;
+    return other_defn;
+  }
+  if ((kind == Token::kEQ_STRICT) &&
+      (constant.raw() == Bool::False().raw()) &&
+      other_defn->IsComparison() &&
+      (other->Type()->ToCid() == kBoolCid) &&
+      other_defn->HasOnlyUse(other)) {
+    *negated = true;
+    return other_defn;
   }
   return compare;
 }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 7d66fe0..4bfc463 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -366,7 +366,7 @@
 
 
 // NotNullConstrainedCompileType represents not-null constraint applied to
-// the source compile type. Result is non-nullable version of the incomming
+// the source compile type. Result is non-nullable version of the incoming
 // compile type. It is used to represent compile type propagated downwards
 // from strict comparison with the null constant.
 class NotNullConstrainedCompileType : public ConstrainedCompileType {
@@ -506,6 +506,8 @@
   bool Equals(Value* other) const;
 
  private:
+  friend class FlowGraphPrinter;
+
   Definition* definition_;
   Value* previous_use_;
   Value* next_use_;
@@ -1752,6 +1754,7 @@
 
  protected:
   friend class RangeAnalysis;
+  friend class Value;
 
   Range* range_;
   CompileType* type_;
@@ -3757,6 +3760,8 @@
 
   virtual bool MayThrow() const { return false; }
 
+  virtual Definition* Canonicalize(FlowGraph* flow_graph);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BooleanNegateInstr);
 };
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ae66602..b073679 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1635,6 +1635,18 @@
 }
 
 
+RawAbstractType* Class::DeclarationType() const {
+  const TypeArguments& args = TypeArguments::Handle(type_parameters());
+  const Type& type = Type::Handle(Type::New(
+      *this,
+      args,
+      Scanner::kDummyTokenIndex));
+  return ClassFinalizer::FinalizeType(*this,
+                                      type,
+                                      ClassFinalizer::kCanonicalize);
+}
+
+
 template <class FakeObject>
 RawClass* Class::New() {
   ASSERT(Object::class_class() != Class::null());
@@ -7003,17 +7015,11 @@
 
 
 static RawString* MakeTypeParameterMetaName(const TypeParameter& param) {
-  const Array& parts = Array::Handle(Array::New(3));
-  String& part = String::Handle();
-  part ^= MakeClassMetaName(Class::Handle(param.parameterized_class()));
-  parts.SetAt(0, part);
-  // We need to choose something different from field/function names, because it
-  // is allowed to have type parameters and fields/functions with the same name
-  // in a class.
-  parts.SetAt(1, Symbols::Slash());
-  part ^= param.name();
-  parts.SetAt(2, part);
-  return String::ConcatAll(parts);
+  const String& cname = String::Handle(
+      MakeClassMetaName(Class::Handle(param.parameterized_class())));
+  String& pname = String::Handle(param.name());
+  pname = String::Concat(Symbols::At(), pname);
+  return String::Concat(cname, pname);
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index fb0cb8a..387b734 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -709,6 +709,14 @@
   // in superclass clauses.
   RawAbstractType* RareType() const;
 
+  // Return the Type whose arguments are the type parameters declared by this
+  // class preceded by the type arguments declared for superclasses, etc.
+  // e.g. given
+  // class B<T, S>
+  // class C<R> extends B<R, int>
+  // C.DeclarationType() --> C [R, int, R]
+  RawAbstractType* DeclarationType() const;
+
   RawLibrary* library() const { return raw_ptr()->library_; }
   void set_library(const Library& value) const;
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index bf85c9e..2cf980e 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -531,9 +531,10 @@
     name_pos = 0;
     name = NULL;
     redirect_name = NULL;
-    constructor_name = NULL;
+    dict_name = NULL;
     params.Clear();
     kind = RawFunction::kRegularFunction;
+    field_ = NULL;
   }
   bool IsConstructor() const {
     return (kind == RawFunction::kConstructor) && !has_static;
@@ -550,6 +551,23 @@
   bool IsSetter() const {
     return kind == RawFunction::kSetterFunction;
   }
+  const char* ToCString() const {
+    if (field_ != NULL) {
+      return "field";
+    } else if (IsConstructor()) {
+      return "constructor";
+    } else if (IsFactory()) {
+      return "factory";
+    } else if (IsGetter()) {
+      return "getter";
+    } else if (IsSetter()) {
+      return "setter";
+    }
+    return "method";
+  }
+  String* DictName() const {
+    return (dict_name  != NULL) ? dict_name : name;
+  }
   bool has_abstract;
   bool has_external;
   bool has_final;
@@ -566,11 +584,16 @@
   String* name;
   // For constructors: NULL or name of redirected to constructor.
   String* redirect_name;
+  // dict_name is the name used for the class namespace, if it
+  // differs from 'name'.
   // For constructors: NULL for unnamed constructor,
   // identifier after classname for named constructors.
-  String* constructor_name;
+  // For getters and setters: unmangled name.
+  String* dict_name;
   ParamList params;
   RawFunction::Kind kind;
+  // NULL for functions, field object for static or instance fields.
+  Field* field_;
 };
 
 
@@ -587,67 +610,7 @@
         fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) {
   }
 
-  // Parameter 'name' is the unmangled name, i.e. without the setter
-  // name mangling.
-  bool FunctionNameExists(const String& name, RawFunction::Kind kind) const {
-    // First check if a function or field of same name exists.
-    if ((kind != RawFunction::kSetterFunction) && FunctionExists(name)) {
-      return true;
-    }
-    // Now check whether there is a field and whether its implicit getter
-    // or setter collides with the name.
-    Field* field = LookupField(name);
-    if (field != NULL) {
-      if (kind == RawFunction::kSetterFunction) {
-        // It's ok to have an implicit getter, it does not collide with
-        // this setter function.
-        if (!field->is_final()) {
-          return true;
-        }
-      } else {
-        // The implicit getter of the field collides with the name.
-        return true;
-      }
-    }
-
-    String& accessor_name = String::Handle();
-    if (kind == RawFunction::kSetterFunction) {
-      // Check if a setter function of same name exists.
-      accessor_name = Field::SetterName(name);
-      if (FunctionExists(accessor_name)) {
-        return true;
-      }
-    } else {
-      // Check if a getter function of same name exists.
-      accessor_name = Field::GetterName(name);
-      if (FunctionExists(accessor_name)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  bool FieldNameExists(const String& name, bool check_setter) const {
-    // First check if a function or field of same name exists.
-    if (FunctionExists(name) || FieldExists(name)) {
-      return true;
-    }
-    // Now check if a getter/setter function of same name exists.
-    String& getter_name = String::Handle(Field::GetterName(name));
-    if (FunctionExists(getter_name)) {
-      return true;
-    }
-    if (check_setter) {
-      String& setter_name = String::Handle(Field::SetterName(name));
-      if (FunctionExists(setter_name)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
   void AddFunction(const Function& function) {
-    ASSERT(!FunctionExists(String::Handle(function.name())));
     functions_.Add(function);
   }
 
@@ -656,7 +619,6 @@
   }
 
   void AddField(const Field& field) {
-    ASSERT(!FieldExists(String::Handle(field.name())));
     fields_.Add(field);
   }
 
@@ -705,40 +667,6 @@
   }
 
  private:
-  Field* LookupField(const String& name) const {
-    String& test_name = String::Handle();
-    Field& field = Field::Handle();
-    for (int i = 0; i < fields_.Length(); i++) {
-      field ^= fields_.At(i);
-      test_name = field.name();
-      if (name.Equals(test_name)) {
-        return &field;
-      }
-    }
-    return NULL;
-  }
-
-  bool FieldExists(const String& name) const {
-    return LookupField(name) != NULL;
-  }
-
-  Function* LookupFunction(const String& name) const {
-    String& test_name = String::Handle();
-    Function& func = Function::Handle();
-    for (int i = 0; i < functions_.Length(); i++) {
-      func ^= functions_.At(i);
-      test_name = func.name();
-      if (name.Equals(test_name)) {
-        return &func;
-      }
-    }
-    return NULL;
-  }
-
-  bool FunctionExists(const String& name) const {
-    return LookupFunction(name) != NULL;
-  }
-
   const Class& clazz_;
   const String& class_name_;
   intptr_t token_pos_;   // Token index of "class" keyword.
@@ -3074,21 +3002,19 @@
     CheckOperatorArity(*method);
   }
 
-  if (members->FunctionNameExists(*method->name, method->kind)) {
-    ErrorMsg(method->name_pos,
-             "field or method '%s' already defined", method->name->ToCString());
-  }
-
   // Mangle the name for getter and setter functions and check function
   // arity.
   if (method->IsGetter() || method->IsSetter()) {
     int expected_num_parameters = 0;
     if (method->IsGetter()) {
       expected_num_parameters = (method->has_static) ? 0 : 1;
+      method->dict_name = method->name;
       method->name = &String::ZoneHandle(Field::GetterSymbol(*method->name));
     } else {
       ASSERT(method->IsSetter());
       expected_num_parameters = (method->has_static) ? 1 : 2;
+      method->dict_name =
+          &String::ZoneHandle(String::Concat(*method->name, Symbols::Equals()));
       method->name = &String::ZoneHandle(Field::SetterSymbol(*method->name));
     }
     if ((method->params.num_fixed_parameters != expected_num_parameters) ||
@@ -3316,13 +3242,9 @@
   if (!field->has_static && field->has_const) {
     ErrorMsg(field->name_pos, "instance field may not be 'const'");
   }
-  if (members->FieldNameExists(*field->name, !field->has_final)) {
-    ErrorMsg(field->name_pos,
-             "field or method '%s' already defined", field->name->ToCString());
-  }
   Function& getter = Function::Handle();
   Function& setter = Function::Handle();
-  Field& class_field = Field::Handle();
+  Field& class_field = Field::ZoneHandle();
   Instance& init_value = Instance::Handle();
   while (true) {
     bool has_initializer = CurrentToken() == Token::kASSIGN;
@@ -3370,6 +3292,7 @@
     class_field.set_type(*field->type);
     class_field.set_has_initializer(has_initializer);
     members->AddField(class_field);
+    field->field_ = &class_field;
     if (field->metadata_pos >= 0) {
       library_.AddFieldMetadata(class_field, field->metadata_pos);
     }
@@ -3463,6 +3386,34 @@
 }
 
 
+void Parser::CheckMemberNameConflict(ClassDesc* members,
+                                     MemberDesc* member) {
+  const String& name = *member->DictName();
+  if (name.Equals(members->class_name())) {
+    ErrorMsg(member->name_pos,
+             "%s '%s' conflicts with class name",
+             member->ToCString(),
+             name.ToCString());
+  }
+  if (members->clazz().LookupTypeParameter(name) != TypeParameter::null()) {
+    ErrorMsg(member->name_pos,
+             "%s '%s' conflicts with type parameter",
+             member->ToCString(),
+             name.ToCString());
+  }
+  for (int i = 0; i < members->members().length(); i++) {
+    MemberDesc* existing_member = &members->members()[i];
+    if (name.Equals(*existing_member->DictName())) {
+      ErrorMsg(member->name_pos,
+               "%s '%s' conflicts with previously declared %s",
+               member->ToCString(),
+               name.ToCString(),
+               existing_member->ToCString());
+    }
+  }
+}
+
+
 void Parser::ParseClassMemberDefinition(ClassDesc* members,
                                         intptr_t metadata_pos) {
   TRACE_PARSER("ParseClassMemberDefinition");
@@ -3579,8 +3530,8 @@
     if (CurrentToken() == Token::kPERIOD) {
       // Named constructor.
       ConsumeToken();
-      member.constructor_name = ExpectIdentifier("identifier expected");
-      *member.name = String::Concat(*member.name, *member.constructor_name);
+      member.dict_name = ExpectIdentifier("identifier expected");
+      *member.name = String::Concat(*member.name, *member.dict_name);
     }
     // Ensure that names are symbols.
     *member.name = Symbols::New(*member.name);
@@ -3643,13 +3594,6 @@
   }
 
   ASSERT(member.name != NULL);
-  if (member.kind != RawFunction::kConstructor) {
-    if (member.name->Equals(members->class_name())) {
-      ErrorMsg(member.name_pos,
-               "class member must not have the same name as its class");
-    }
-  }
-
   if (CurrentToken() == Token::kLPAREN || member.IsGetter()) {
     // Constructor or method.
     if (member.type == NULL) {
@@ -3678,6 +3622,7 @@
     UnexpectedToken();
   }
   current_member_ = NULL;
+  CheckMemberNameConflict(members, &member);
   members->AddMember(member);
 }
 
@@ -3945,25 +3890,15 @@
 }
 
 
-// Check for cycles in constructor redirection. Also check whether a
-// named constructor collides with the name of another class member.
+// Check for cycles in constructor redirection.
 void Parser::CheckConstructors(ClassDesc* class_desc) {
   // Check for cycles in constructor redirection.
   const GrowableArray<MemberDesc>& members = class_desc->members();
   for (int i = 0; i < members.length(); i++) {
     MemberDesc* member = &members[i];
-
-    if (member->constructor_name != NULL) {
-      // Check whether constructor name conflicts with a member name.
-      if (class_desc->FunctionNameExists(
-          *member->constructor_name, member->kind)) {
-        ErrorMsg(member->name_pos,
-                 "Named constructor '%s' conflicts with method or field '%s'",
-                 member->name->ToCString(),
-                 member->constructor_name->ToCString());
-      }
+    if (member->redirect_name == NULL) {
+      continue;
     }
-
     GrowableArray<MemberDesc*> ctors;
     while ((member != NULL) && (member->redirect_name != NULL)) {
       ASSERT(member->IsConstructor());
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 86f40e2..cd5dc73 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -384,6 +384,7 @@
   void ParseQualIdent(QualIdent* qual_ident);
   void ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method);
   void ParseFieldDefinition(ClassDesc* members, MemberDesc* field);
+  void CheckMemberNameConflict(ClassDesc* members, MemberDesc* member);
   void ParseClassMemberDefinition(ClassDesc* members,
                                   intptr_t metadata_pos);
   void ParseFormalParameter(bool allow_explicit_default_value,
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 2cddc5a..8e78555 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -40,7 +40,7 @@
   const intptr_t argv_offset = NativeArguments::argv_offset();
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ EnterStubFrame();
 
   // Load current Isolate pointer from Context structure into R0.
   __ ldr(R0, FieldAddress(CTX, Context::isolate_offset()));
@@ -73,7 +73,8 @@
 
   ASSERT(argv_offset == 2 * kWordSize);
   __ add(R2, FP, ShifterOperand(R4, LSL, 2));  // Compute argv.
-  __ AddImmediate(R2, kWordSize);  // Set argv in NativeArguments.
+  // Set argv in NativeArguments.
+  __ AddImmediate(R2, kParamEndSlotFromFp * kWordSize);
 
   ASSERT(retval_offset == 3 * kWordSize);
   __ add(R3, R2, ShifterOperand(kWordSize));  // Retval is next to 1st argument.
@@ -95,7 +96,7 @@
   // Cache Context pointer into CTX while executing Dart code.
   __ mov(CTX, ShifterOperand(R2));
 
-  __ LeaveFrame((1 << FP) | (1 << LR));
+  __ LeaveStubFrame();
   __ Ret();
 }
 
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 6a06fe1..aea2d8e 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -42,10 +42,7 @@
 
   __ SetPrologueOffset();
   __ TraceSimMsg("CallToRuntimeStub");
-  __ addiu(SP, SP, Immediate(-2 * kWordSize));
-  __ sw(RA, Address(SP, 1 * kWordSize));
-  __ sw(FP, Address(SP, 0 * kWordSize));
-  __ mov(FP, SP);
+  __ EnterStubFrame();
 
   // Load current Isolate pointer from Context structure into A0.
   __ lw(A0, FieldAddress(CTX, Context::isolate_offset()));
@@ -79,7 +76,8 @@
   ASSERT(argv_offset == 2 * kWordSize);
   __ sll(A2, S4, 2);
   __ addu(A2, FP, A2);  // Compute argv.
-  __ addiu(A2, A2, Immediate(kWordSize));  // Set argv in NativeArguments.
+  // Set argv in NativeArguments.
+  __ addiu(A2, A2, Immediate(kParamEndSlotFromFp * kWordSize));
 
   ASSERT(retval_offset == 3 * kWordSize);
 
@@ -104,11 +102,7 @@
   // Cache Context pointer into CTX while executing Dart code.
   __ mov(CTX, A2);
 
-  __ mov(SP, FP);
-  __ lw(RA, Address(SP, 1 * kWordSize));
-  __ lw(FP, Address(SP, 0 * kWordSize));
-  __ Ret();
-  __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
+  __ LeaveStubFrameAndReturn();
 }
 
 
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 7a34fef..03bf628 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -53,15 +53,15 @@
                                      Dart_Handle library,
                                      Dart_Handle url) {
   if (!Dart_IsLibrary(library)) {
-    return Dart_Error("not a library");
+    return Dart_NewApiError("not a library");
   }
   if (!Dart_IsString(url)) {
-    return Dart_Error("url is not a string");
+    return Dart_NewApiError("url is not a string");
   }
   const char* url_chars = NULL;
   Dart_Handle result = Dart_StringToCString(url, &url_chars);
   if (Dart_IsError(result)) {
-    return Dart_Error("accessing url characters failed");
+    return Dart_NewApiError("accessing url characters failed");
   }
   Dart_Handle library_url = Dart_LibraryUrl(library);
   const char* library_url_string = NULL;
@@ -91,7 +91,7 @@
     } else if (DartUtils::IsDartBuiltinLibURL(url_chars)) {
       return Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
     } else {
-      return Dart_Error("Do not know how to load '%s'", url_chars);
+      return DartUtils::NewError("Do not know how to load '%s'", url_chars);
     }
   }
   if (is_io_library) {
diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart
index 661a86b..e8929de 100644
--- a/sdk/lib/_collection_dev/list.dart
+++ b/sdk/lib/_collection_dev/list.dart
@@ -9,67 +9,80 @@
  *
  * Intended to mix-in on top of [ListMixin] for fixed-length lists.
  */
-abstract class FixedLengthListMixin<E>  {
+abstract class FixedLengthListMixin<E> {
+  /** This operation is not supported by a fixed length list. */
   void set length(int newLength) {
     throw new UnsupportedError(
         "Cannot change the length of a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void add(E value) {
     throw new UnsupportedError(
         "Cannot add to a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void insert(int index, E value) {
     throw new UnsupportedError(
         "Cannot add to a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void insertAll(int at, Iterable<E> iterable) {
     throw new UnsupportedError(
         "Cannot add to a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void addAll(Iterable<E> iterable) {
     throw new UnsupportedError(
         "Cannot add to a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   bool remove(Object element) {
     throw new UnsupportedError(
         "Cannot remove from a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void removeWhere(bool test(E element)) {
     throw new UnsupportedError(
         "Cannot remove from a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void retainWhere(bool test(E element)) {
     throw new UnsupportedError(
         "Cannot remove from a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void clear() {
     throw new UnsupportedError(
         "Cannot clear a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   E removeAt(int index) {
     throw new UnsupportedError(
         "Cannot remove from a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   E removeLast() {
     throw new UnsupportedError(
         "Cannot remove from a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void removeRange(int start, int end) {
     throw new UnsupportedError(
         "Cannot remove from a fixed-length list");
   }
 
+  /** This operation is not supported by a fixed length list. */
   void replaceRange(int start, int end, Iterable<E> iterable) {
     throw new UnsupportedError(
         "Cannot remove from a fixed-length list");
@@ -85,96 +98,115 @@
  */
 abstract class UnmodifiableListMixin<E> implements List<E> {
 
+  /** This operation is not supported by an unmodifiable list. */
   void operator []=(int index, E value) {
     throw new UnsupportedError(
         "Cannot modify an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void set length(int newLength) {
     throw new UnsupportedError(
         "Cannot change the length of an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void setAll(int at, Iterable<E> iterable) {
     throw new UnsupportedError(
         "Cannot modify an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void add(E value) {
     throw new UnsupportedError(
       "Cannot add to an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   E insert(int index, E value) {
     throw new UnsupportedError(
         "Cannot add to an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void insertAll(int at, Iterable<E> iterable) {
     throw new UnsupportedError(
         "Cannot add to an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void addAll(Iterable<E> iterable) {
     throw new UnsupportedError(
         "Cannot add to an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   bool remove(Object element) {
     throw new UnsupportedError(
         "Cannot remove from an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void removeWhere(bool test(E element)) {
     throw new UnsupportedError(
         "Cannot remove from an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void retainWhere(bool test(E element)) {
     throw new UnsupportedError(
         "Cannot remove from an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void sort([Comparator<E> compare]) {
     throw new UnsupportedError(
         "Cannot modify an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void shuffle([Random random]) {
     throw new UnsupportedError(
         "Cannot modify an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void clear() {
     throw new UnsupportedError(
         "Cannot clear an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   E removeAt(int index) {
     throw new UnsupportedError(
         "Cannot remove from an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   E removeLast() {
     throw new UnsupportedError(
         "Cannot remove from an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     throw new UnsupportedError(
         "Cannot modify an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void removeRange(int start, int end) {
     throw new UnsupportedError(
         "Cannot remove from an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void replaceRange(int start, int end, Iterable<E> iterable) {
     throw new UnsupportedError(
         "Cannot remove from an unmodifiable list");
   }
 
+  /** This operation is not supported by an unmodifiable list. */
   void fillRange(int start, int end, [E fillValue]) {
     throw new UnsupportedError(
         "Cannot modify an unmodifiable list");
@@ -239,22 +271,27 @@
     }
   }
 
+  /** This operation is not supported by an unmodifiable map. */
   void operator[]= (int key, E value) {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
 
+  /** This operation is not supported by an unmodifiable map. */
   E putIfAbsent(int key, E ifAbsent()) {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
 
+  /** This operation is not supported by an unmodifiable map. */
   E remove(int key) {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
 
+  /** This operation is not supported by an unmodifiable map. */
   void clear() {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
 
+  /** This operation is not supported by an unmodifiable map. */
   void addAll(Map<int, E> other) {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
diff --git a/sdk/lib/_internal/compiler/compiler.dart b/sdk/lib/_internal/compiler/compiler.dart
index 215f248..b6e5394 100644
--- a/sdk/lib/_internal/compiler/compiler.dart
+++ b/sdk/lib/_internal/compiler/compiler.dart
@@ -11,11 +11,20 @@
 // methods of library will result in an Error being thrown.
 
 /**
- * Returns a future that completes to the source corresponding to
- * [uri]. If an exception occurs, the future completes with this
- * exception.
+ * Returns a future that completes to the source corresponding to [uri].
+ * If an exception occurs, the future completes with this exception.
+ *
+ * The source can be represented either as a [:List<int>:] of UTF-8 bytes or as
+ * a [String].
+ *
+ * The following text is non-normative:
+ *
+ * It is recommended to return a UTF-8 encoded list of bytes because the scanner
+ * is more efficient in this case. In either case, the data structure is
+ * expected to hold a zero element at the last position. If this is not the
+ * case, the entire data structure is copied before scanning.
  */
-typedef Future<String> CompilerInputProvider(Uri uri);
+typedef Future/*<String | List<int>>*/ CompilerInputProvider(Uri uri);
 
 /// Deprecated, please use [CompilerInputProvider] instead.
 typedef Future<String> ReadStringFromUri(Uri uri);
diff --git a/sdk/lib/_internal/compiler/implementation/apiimpl.dart b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
index 2b56ac0..f72214b 100644
--- a/sdk/lib/_internal/compiler/implementation/apiimpl.dart
+++ b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
@@ -15,7 +15,7 @@
 import 'source_file.dart';
 
 class Compiler extends leg.Compiler {
-  api.ReadStringFromUri provider;
+  api.CompilerInputProvider provider;
   api.DiagnosticHandler handler;
   final Uri libraryRoot;
   final Uri packageRoot;
@@ -176,8 +176,18 @@
     // [Future] to ensure that we never execute an asynchronous action without setting
     // up the current element of the compiler.
     return new Future.sync(() => callUserProvider(resourceUri))
-        .then((String text) {
-      SourceFile sourceFile = new SourceFile(resourceUri.toString(), text);
+        .then((data) {
+      SourceFile sourceFile;
+      String resourceUriString = resourceUri.toString();
+      if (data is List<int>) {
+        sourceFile = new Utf8BytesSourceFile(resourceUriString, data);
+      } else if (data is String) {
+        sourceFile = new StringSourceFile(resourceUriString, data);
+      } else {
+        String message = "Expected a 'String' or a 'List<int>' from the input "
+                         "provider, but got: ${Error.safeToString(data)}.";
+        reportReadError(message);
+      }
       // We use [readableUri] as the URI for the script since need to preserve
       // the scheme in the script because [Script.uri] is used for resolving
       // relative URIs mentioned in the script. See the comment on
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index a91f9ab..0bf8280 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -13,8 +13,8 @@
 import "elements/modelx.dart" show ElementX, FunctionElementX, ClassElementX;
 
 class ClosureNamer {
-  SourceString getClosureVariableName(SourceString name, int id) {
-    return new SourceString("${name.slowToString()}_$id");
+  String getClosureVariableName(String name, int id) {
+    return "${name}_$id";
   }
 }
 
@@ -71,7 +71,7 @@
   /// The source variable this element refers to.
   final Element variableElement;
 
-  ClosureFieldElement(SourceString name,
+  ClosureFieldElement(String name,
                       this.variableElement,
                       ClassElement enclosing)
       : super(name, ElementKind.FIELD, enclosing);
@@ -92,7 +92,7 @@
   // The names of closure variables don't need renaming, since their use is very
   // simple and they have 1-character names in the minified mode.
   bool hasFixedBackendName() => true;
-  String fixedBackendName() => name.slowToString();
+  String fixedBackendName() => name;
 
   DartType computeType(Compiler compiler) {
     return variableElement.computeType(compiler);
@@ -111,7 +111,7 @@
   final FunctionExpression node;
 
   ClosureClassElement(this.node,
-                      SourceString name,
+                      String name,
                       Compiler compiler,
                       this.methodElement,
                       Element enclosingElement)
@@ -148,7 +148,7 @@
 // move these classes to elements/modelx.dart or see if we can find a
 // more general solution.
 class BoxElement extends ElementX {
-  BoxElement(SourceString name, Element enclosingElement)
+  BoxElement(String name, Element enclosingElement)
       : super(name, ElementKind.VARIABLE, enclosingElement);
 
   DartType computeType(Compiler compiler) => compiler.types.dynamicType;
@@ -158,7 +158,7 @@
 // move these classes to elements/modelx.dart or see if we can find a
 // more general solution.
 class BoxFieldElement extends ElementX {
-  BoxFieldElement(SourceString name,
+  BoxFieldElement(String name,
                   this.variableElement,
                   BoxElement enclosingBox)
       : super(name, ElementKind.FIELD, enclosingBox);
@@ -175,7 +175,7 @@
 // more general solution.
 class ThisElement extends ElementX {
   ThisElement(Element enclosing)
-      : super(const SourceString('this'), ElementKind.PARAMETER, enclosing);
+      : super('this', ElementKind.PARAMETER, enclosing);
 
   bool isAssignable() => false;
 
@@ -191,7 +191,7 @@
 // more general solution.
 class CheckVariableElement extends ElementX {
   Element parameter;
-  CheckVariableElement(SourceString name, this.parameter, Element enclosing)
+  CheckVariableElement(String name, this.parameter, Element enclosing)
       : super(name, ElementKind.VARIABLE, enclosing);
 
   DartType computeType(Compiler compiler) => compiler.types.dynamicType;
@@ -355,7 +355,7 @@
   }
 
   void translateLazyInitializer(Element element, SendSet node) {
-    assert(node.assignmentOperator.source == const SourceString("="));
+    assert(node.assignmentOperator.source == "=");
     Expression initialValue = node.argumentsNode.nodes.head;
     visitInvokable(element, node, () { visit(initialValue); });
     updateClosures();
@@ -396,7 +396,7 @@
       ClassElement closureElement = data.closureClassElement;
       assert(closureElement != null ||
              (fieldCaptures.isEmpty && boxes.isEmpty));
-      void addElement(Element element, SourceString name) {
+      void addElement(Element element, String name) {
         Element fieldElement = new ClosureFieldElement(
             name, element, closureElement);
         closureElement.addMember(fieldElement, compiler);
@@ -411,8 +411,7 @@
       for (Element capturedElement in
                Elements.sortedByPosition(fieldCaptures)) {
         int id = closureFieldCounter++;
-        SourceString name =
-            namer.getClosureVariableName(capturedElement.name, id);
+        String name = namer.getClosureVariableName(capturedElement.name, id);
         addElement(capturedElement, name);
       }
       closureElement.reverseBackendMembers();
@@ -613,20 +612,18 @@
       if (capturedVariableMapping.containsKey(element)) {
         if (box == null) {
           // TODO(floitsch): construct better box names.
-          SourceString boxName =
-              namer.getClosureVariableName(const SourceString('box'),
-                                           closureFieldCounter++);
+          String boxName =
+              namer.getClosureVariableName('box', closureFieldCounter++);
           box = new BoxElement(boxName, currentElement);
         }
-        String elementName = element.name.slowToString();
-        SourceString boxedName =
-            namer.getClosureVariableName(new SourceString(elementName),
-                                         boxedFieldCounter++);
+        String elementName = element.name;
+        String boxedName =
+            namer.getClosureVariableName(elementName, boxedFieldCounter++);
         // TODO(kasperl): Should this be a FieldElement instead?
         Element boxed = new BoxFieldElement(boxedName, element, box);
         // No need to rename the fields of a box, so we give them a native name
         // right now.
-        boxed.setFixedBackendName(boxedName.slowToString());
+        boxed.setFixedBackendName(boxedName);
         scopeMapping[element] = boxed;
         capturedVariableMapping[element] = boxed;
       }
@@ -678,11 +675,11 @@
   /** Returns a non-unique name for the given closure element. */
   String computeClosureName(Element element) {
     Link<String> parts = const Link<String>();
-    SourceString ownName = element.name;
-    if (ownName == null || ownName.stringValue == "") {
+    String ownName = element.name;
+    if (ownName == null || ownName == "") {
       parts = parts.prepend("closure");
     } else {
-      parts = parts.prepend(ownName.slowToString());
+      parts = parts.prepend(ownName);
     }
     for (Element enclosingElement = element.enclosingElement;
          enclosingElement != null &&
@@ -700,9 +697,9 @@
         parts = parts.prepend(
             Elements.reconstructConstructorName(enclosingElement));
       } else {
-        SourceString surroundingName =
+        String surroundingName =
             Elements.operatorNameToIdentifier(enclosingElement.name);
-        parts = parts.prepend(surroundingName.slowToString());
+        parts = parts.prepend(surroundingName);
       }
       // A generative constructors's parent is the class; the class name is
       // already part of the generative constructor's name.
@@ -714,7 +711,7 @@
   }
 
   ClosureClassMap globalizeClosure(FunctionExpression node, Element element) {
-    SourceString closureName = new SourceString(computeClosureName(element));
+    String closureName = computeClosureName(element);
     ClassElement globalizedElement = new ClosureClassElement(
         node, closureName, compiler, element, element.getCompilationUnit());
     FunctionElement callElement =
diff --git a/sdk/lib/_internal/compiler/implementation/common.dart b/sdk/lib/_internal/compiler/implementation/common.dart
index 3c069ca..2826d9e 100644
--- a/sdk/lib/_internal/compiler/implementation/common.dart
+++ b/sdk/lib/_internal/compiler/implementation/common.dart
@@ -13,7 +13,6 @@
     MessageKind,
     NullConstant,
     Selector,
-    SourceString,
     TreeElements,
     TypeConstant,
     invariant;
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 24b6d46..735d2f1 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -332,7 +332,7 @@
       keysType = new InterfaceType(compiler.listClass, arguments);
     }
     ListConstant keysList = new ListConstant(keysType, keys);
-    SourceString className = onlyStringKeys
+    String className = onlyStringKeys
         ? (hasProtoKey ? MapConstant.DART_PROTO_CLASS
                        : MapConstant.DART_STRING_CLASS)
         : MapConstant.DART_GENERAL_CLASS;
@@ -453,7 +453,7 @@
       if (receiverConstant == null) return null;
       Operator op = send.selector;
       Constant folded;
-      switch (op.source.stringValue) {
+      switch (op.source) {
         case "!":
           folded = constantSystem.not.fold(receiverConstant);
           break;
@@ -476,7 +476,7 @@
       if (left == null || right == null) return null;
       Operator op = send.selector.asOperator();
       Constant folded = null;
-      switch (op.source.stringValue) {
+      switch (op.source) {
         case "+":
           folded = constantSystem.add.fold(left, right);
           break;
@@ -638,7 +638,7 @@
   }
 
   Constant makeConstructedConstant(
-      Node node, InterfaceType type, FunctionElement constructor,
+      Spannable node, InterfaceType type, FunctionElement constructor,
       List<Constant> getArguments(FunctionElement constructor)) {
     if (constructor.isRedirectingFactory) {
       type = constructor.computeTargetType(compiler, type);
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 6098512..b0e1444 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -537,35 +537,35 @@
   MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask;
   String buildId;
 
-  static const SourceString MAIN = const SourceString('main');
-  static const SourceString CALL_OPERATOR_NAME = const SourceString('call');
-  static const SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod');
+  static const String MAIN = 'main';
+  static const String CALL_OPERATOR_NAME = 'call';
+  static const String NO_SUCH_METHOD = 'noSuchMethod';
   static const int NO_SUCH_METHOD_ARG_COUNT = 1;
-  static const SourceString CREATE_INVOCATION_MIRROR =
-      const SourceString('createInvocationMirror');
+  static const String CREATE_INVOCATION_MIRROR =
+      'createInvocationMirror';
 
   // TODO(ahe): Rename this field and move this logic to backend, similar to how
   // we disable tree-shaking when seeing disableTreeShaking in js_mirrors.dart.
-  static const SourceString INVOKE_ON =
-      const SourceString('_getCachedInvocation');
+  static const String INVOKE_ON =
+      '_getCachedInvocation';
 
-  static const SourceString RUNTIME_TYPE = const SourceString('runtimeType');
-  static const SourceString START_ROOT_ISOLATE =
-      const SourceString('startRootIsolate');
+  static const String RUNTIME_TYPE = 'runtimeType';
+  static const String START_ROOT_ISOLATE =
+      'startRootIsolate';
 
   static const String UNDETERMINED_BUILD_ID =
       "build number could not be determined";
 
   final Selector iteratorSelector =
-      new Selector.getter(const SourceString('iterator'), null);
+      new Selector.getter('iterator', null);
   final Selector currentSelector =
-      new Selector.getter(const SourceString('current'), null);
+      new Selector.getter('current', null);
   final Selector moveNextSelector =
-      new Selector.call(const SourceString('moveNext'), null, 0);
+      new Selector.call('moveNext', null, 0);
   final Selector noSuchMethodSelector = new Selector.call(
       Compiler.NO_SUCH_METHOD, null, Compiler.NO_SUCH_METHOD_ARG_COUNT);
   final Selector symbolValidatedConstructorSelector = new Selector.call(
-      const SourceString('validated'), null, 1);
+      'validated', null, 1);
 
   bool enabledNoSuchMethod = false;
   bool enabledRuntimeType = false;
@@ -802,19 +802,19 @@
     if (uri == new Uri(scheme: 'dart', path: 'mirrors')) {
       mirrorsLibrary = library;
       mirrorSystemClass =
-          findRequiredElement(library, const SourceString('MirrorSystem'));
+          findRequiredElement(library, 'MirrorSystem');
       mirrorsUsedClass =
-          findRequiredElement(library, const SourceString('MirrorsUsed'));
+          findRequiredElement(library, 'MirrorsUsed');
     } else if (uri == new Uri(scheme: 'dart', path: 'typed_data')) {
       typedDataLibrary = library;
       typedDataClass =
-          findRequiredElement(library, const SourceString('TypedData'));
+          findRequiredElement(library, 'TypedData');
     } else if (uri == new Uri(scheme: 'dart', path: '_collection-dev')) {
       symbolImplementationClass =
-          findRequiredElement(library, const SourceString('Symbol'));
+          findRequiredElement(library, 'Symbol');
     } else if (uri == new Uri(scheme: 'dart', path: 'async')) {
       deferredLibraryClass =
-          findRequiredElement(library, const SourceString('DeferredLibrary'));
+          findRequiredElement(library, 'DeferredLibrary');
     } else if (isolateHelperLibrary == null
 	       && (uri == new Uri(scheme: 'dart', path: '_isolate_helper'))) {
       isolateHelperLibrary = library;
@@ -825,13 +825,13 @@
     return backend.onLibraryLoaded(library, uri);
   }
 
-  Element findRequiredElement(LibraryElement library, SourceString name) {
+  Element findRequiredElement(LibraryElement library, String name) {
     var element = library.find(name);
     if (element == null) {
       internalErrorOnElement(
           library,
           'The library "${library.canonicalUri}" does not contain required '
-          'element: ${name.slowToString()}');
+          'element: $name');
       }
     return element;
   }
@@ -839,7 +839,7 @@
   void onClassResolved(ClassElement cls) {
     if (mirrorSystemClass == cls) {
       mirrorSystemGetNameFunction =
-        cls.lookupLocalMember(const SourceString('getName'));
+        cls.lookupLocalMember('getName');
     } else if (symbolClass == cls) {
       symbolConstructor = cls.constructors.head;
     } else if (symbolImplementationClass == cls) {
@@ -855,7 +855,7 @@
   void initializeSpecialClasses() {
     final List missingCoreClasses = [];
     ClassElement lookupCoreClass(String name) {
-      ClassElement result = coreLibrary.find(new SourceString(name));
+      ClassElement result = coreLibrary.find(name);
       if (result == null) {
         missingCoreClasses.add(name);
       }
@@ -886,7 +886,7 @@
 
     final List missingHelperClasses = [];
     ClassElement lookupHelperClass(String name) {
-      ClassElement result = jsHelperLibrary.find(new SourceString(name));
+      ClassElement result = jsHelperLibrary.find(name);
       if (result == null) {
         missingHelperClasses.add(name);
       }
@@ -914,7 +914,7 @@
   Element get unnamedListConstructor {
     if (_unnamedListConstructor != null) return _unnamedListConstructor;
     Selector callConstructor = new Selector.callConstructor(
-        const SourceString(""), listClass.getLibrary());
+        "", listClass.getLibrary());
     return _unnamedListConstructor =
         listClass.lookupConstructor(callConstructor);
   }
@@ -923,7 +923,7 @@
   Element get filledListConstructor {
     if (_filledListConstructor != null) return _filledListConstructor;
     Selector callConstructor = new Selector.callConstructor(
-        const SourceString("filled"), listClass.getLibrary());
+        "filled", listClass.getLibrary());
     return _filledListConstructor =
         listClass.lookupConstructor(callConstructor);
   }
@@ -935,14 +935,14 @@
     }).then((LibraryElement library) {
       interceptorsLibrary = library;
 
-      assertMethod = jsHelperLibrary.find(const SourceString('assertHelper'));
-      identicalFunction = coreLibrary.find(const SourceString('identical'));
+      assertMethod = jsHelperLibrary.find('assertHelper');
+      identicalFunction = coreLibrary.find('identical');
 
       initializeSpecialClasses();
 
       functionClass.ensureResolved(this);
       functionApplyMethod =
-          functionClass.lookupLocalMember(const SourceString('apply'));
+          functionClass.lookupLocalMember('apply');
       jsInvocationMirrorClass.ensureResolved(this);
       invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON);
 
@@ -950,7 +950,7 @@
         var uri = new Uri(scheme: 'dart', path: 'mirrors');
         return libraryLoader.loadLibrary(uri, null, uri).then(
             (LibraryElement libraryElement) {
-          documentClass = libraryElement.find(const SourceString('Comment'));
+          documentClass = libraryElement.find('Comment');
         });
       }
     });
@@ -973,7 +973,7 @@
     // multiple times. Implement a better mechanism where we can store
     // such caches in the compiler and get access to them through a
     // suitably maintained static reference to the current compiler.
-    SourceString.canonicalizedValues.clear();
+    StringToken.canonicalizedSubstrings.clear();
     Selector.canonicalizedValues.clear();
     TypedSelector.canonicalizedValues.clear();
 
@@ -1013,12 +1013,12 @@
           reportFatalError(
               mainApp,
               MessageKind.GENERIC,
-              {'text': "Error: Could not find '${MAIN.slowToString()}'."});
+              {'text': "Error: Could not find '$MAIN'."});
         } else if (!analyzeAll) {
           reportFatalError(
               mainApp,
               MessageKind.GENERIC,
-              {'text': "Error: Could not find '${MAIN.slowToString()}'. "
+              {'text': "Error: Could not find '$MAIN'. "
               "No source will be analyzed. "
               "Use '--analyze-all' to analyze all code in the library."});
         }
@@ -1027,7 +1027,7 @@
           reportFatalError(
               main,
               MessageKind.GENERIC,
-              {'text': "Error: '${MAIN.slowToString()}' is not a function."});
+              {'text': "Error: '$MAIN' is not a function."});
         }
         FunctionElement mainMethod = main;
         FunctionSignature parameters = mainMethod.computeSignature(this);
@@ -1036,7 +1036,7 @@
               parameter,
               MessageKind.GENERIC,
               {'text':
-                'Error: "${MAIN.slowToString()}" cannot have parameters.'});
+                "Error: '$MAIN' cannot have parameters."});
         });
       }
 
@@ -1449,15 +1449,15 @@
 
   // TODO(karlklose): split into findHelperFunction and findHelperClass and
   // add a check that the element has the expected kind.
-  Element findHelper(SourceString name)
+  Element findHelper(String name)
       => jsHelperLibrary.findLocal(name);
-  Element findInterceptor(SourceString name)
+  Element findInterceptor(String name)
       => interceptorsLibrary.findLocal(name);
 
-  Element lookupElementIn(ScopeContainerElement container, SourceString name) {
+  Element lookupElementIn(ScopeContainerElement container, String name) {
     Element element = container.localLookup(name);
     if (element == null) {
-      throw 'Could not find ${name.slowToString()} in $container';
+      throw 'Could not find $name in $container';
     }
     return element;
   }
@@ -1556,7 +1556,7 @@
   static withCharacterOffsets(Token begin, Token end,
                      f(int beginOffset, int endOffset)) {
     final beginOffset = begin.charOffset;
-    final endOffset = end.charOffset + end.slowCharCount;
+    final endOffset = end.charOffset + end.charCount;
 
     // [begin] and [end] might be the same for the same empty token. This
     // happens for instance when scanning '$$'.
@@ -1599,6 +1599,11 @@
   return true;
 }
 
+/**
+ * Global
+ */
+bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;
+
 /// A sink that drains into /dev/null.
 class NullSink implements EventSink<String> {
   final String name;
diff --git a/sdk/lib/_internal/compiler/implementation/constant_system.dart b/sdk/lib/_internal/compiler/implementation/constant_system.dart
index 0fff580..b2688b5 100644
--- a/sdk/lib/_internal/compiler/implementation/constant_system.dart
+++ b/sdk/lib/_internal/compiler/implementation/constant_system.dart
@@ -5,7 +5,7 @@
 part of dart2js;
 
 abstract class Operation {
-  SourceString get name;
+  String get name;
   bool isUserDefinable();
 }
 
@@ -72,9 +72,9 @@
   /** Returns true if the [constant] is null at runtime. */
   bool isNull(Constant constant);
 
-  Operation lookupUnary(SourceString operator) {
-    if (operator == const SourceString('-')) return negate;
-    if (operator == const SourceString('~')) return bitNot;
+  Operation lookupUnary(String operator) {
+    if (operator == '-') return negate;
+    if (operator == '~') return bitNot;
     return null;
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart b/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
index b825f68..7be2ed3 100644
--- a/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
+++ b/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
@@ -7,7 +7,7 @@
 const DART_CONSTANT_SYSTEM = const DartConstantSystem();
 
 class BitNotOperation implements UnaryOperation {
-  final SourceString name = const SourceString('~');
+  final String name = '~';
   bool isUserDefinable() => true;
   const BitNotOperation();
   Constant fold(Constant constant) {
@@ -21,7 +21,7 @@
 }
 
 class NegateOperation implements UnaryOperation {
-  final SourceString name = const SourceString('negate');
+  final String name = 'negate';
   bool isUserDefinable() => true;
   const NegateOperation();
   Constant fold(Constant constant) {
@@ -39,7 +39,7 @@
 }
 
 class NotOperation implements UnaryOperation {
-  final SourceString name = const SourceString('!');
+  final String name = '!';
   bool isUserDefinable() => true;
   const NotOperation();
   Constant fold(Constant constant) {
@@ -73,28 +73,28 @@
 }
 
 class BitOrOperation extends BinaryBitOperation {
-  final SourceString name = const SourceString('|');
+  final String name = '|';
   const BitOrOperation();
   int foldInts(int left, int right)  => left | right;
   apply(left, right) => left | right;
 }
 
 class BitAndOperation extends BinaryBitOperation {
-  final SourceString name = const SourceString('&');
+  final String name = '&';
   const BitAndOperation();
   int foldInts(int left, int right) => left & right;
   apply(left, right) => left & right;
 }
 
 class BitXorOperation extends BinaryBitOperation {
-  final SourceString name = const SourceString('^');
+  final String name = '^';
   const BitXorOperation();
   int foldInts(int left, int right) => left ^ right;
   apply(left, right) => left ^ right;
 }
 
 class ShiftLeftOperation extends BinaryBitOperation {
-  final SourceString name = const SourceString('<<');
+  final String name = '<<';
   const ShiftLeftOperation();
   int foldInts(int left, int right) {
     // TODO(floitsch): find a better way to guard against excessive shifts to
@@ -106,7 +106,7 @@
 }
 
 class ShiftRightOperation extends BinaryBitOperation {
-  final SourceString name = const SourceString('>>');
+  final String name = '>>';
   const ShiftRightOperation();
   int foldInts(int left, int right) {
     if (right < 0) return null;
@@ -132,14 +132,14 @@
 }
 
 class BooleanAndOperation extends BinaryBoolOperation {
-  final SourceString name = const SourceString('&&');
+  final String name = '&&';
   const BooleanAndOperation();
   bool foldBools(bool left, bool right) => left && right;
   apply(left, right) => left && right;
 }
 
 class BooleanOrOperation extends BinaryBoolOperation {
-  final SourceString name = const SourceString('||');
+  final String name = '||';
   const BooleanOrOperation();
   bool foldBools(bool left, bool right) => left || right;
   apply(left, right) => left || right;
@@ -178,21 +178,21 @@
 }
 
 class SubtractOperation extends ArithmeticNumOperation {
-  final SourceString name = const SourceString('-');
+  final String name = '-';
   const SubtractOperation();
   num foldNums(num left, num right) => left - right;
   apply(left, right) => left - right;
 }
 
 class MultiplyOperation extends ArithmeticNumOperation {
-  final SourceString name = const SourceString('*');
+  final String name = '*';
   const MultiplyOperation();
   num foldNums(num left, num right) => left * right;
   apply(left, right) => left * right;
 }
 
 class ModuloOperation extends ArithmeticNumOperation {
-  final SourceString name = const SourceString('%');
+  final String name = '%';
   const ModuloOperation();
   int foldInts(int left, int right) {
     if (right == 0) return null;
@@ -203,7 +203,7 @@
 }
 
 class TruncatingDivideOperation extends ArithmeticNumOperation {
-  final SourceString name = const SourceString('~/');
+  final String name = '~/';
   const TruncatingDivideOperation();
   int foldInts(int left, int right) {
     if (right == 0) return null;
@@ -219,7 +219,7 @@
 }
 
 class DivideOperation extends ArithmeticNumOperation {
-  final SourceString name = const SourceString('/');
+  final String name = '/';
   const DivideOperation();
   num foldNums(num left, num right) => left / right;
   bool isDivide() => true;
@@ -227,7 +227,7 @@
 }
 
 class AddOperation implements BinaryOperation {
-  final SourceString name = const SourceString('+');
+  final String name = '+';
   bool isUserDefinable() => true;
   const AddOperation();
   Constant fold(Constant left, Constant right) {
@@ -265,35 +265,35 @@
 }
 
 class LessOperation extends RelationalNumOperation {
-  final SourceString name = const SourceString('<');
+  final String name = '<';
   const LessOperation();
   bool foldNums(num left, num right) => left < right;
   apply(left, right) => left < right;
 }
 
 class LessEqualOperation extends RelationalNumOperation {
-  final SourceString name = const SourceString('<=');
+  final String name = '<=';
   const LessEqualOperation();
   bool foldNums(num left, num right) => left <= right;
   apply(left, right) => left <= right;
 }
 
 class GreaterOperation extends RelationalNumOperation {
-  final SourceString name = const SourceString('>');
+  final String name = '>';
   const GreaterOperation();
   bool foldNums(num left, num right) => left > right;
   apply(left, right) => left > right;
 }
 
 class GreaterEqualOperation extends RelationalNumOperation {
-  final SourceString name = const SourceString('>=');
+  final String name = '>=';
   const GreaterEqualOperation();
   bool foldNums(num left, num right) => left >= right;
   apply(left, right) => left >= right;
 }
 
 class EqualsOperation implements BinaryOperation {
-  final SourceString name = const SourceString('==');
+  final String name = '==';
   bool isUserDefinable() => true;
   const EqualsOperation();
   Constant fold(Constant left, Constant right) {
@@ -316,7 +316,7 @@
 }
 
 class IdentityOperation implements BinaryOperation {
-  final SourceString name = const SourceString('===');
+  final String name = '===';
   bool isUserDefinable() => false;
   const IdentityOperation();
   BoolConstant fold(Constant left, Constant right) {
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index a8ac524..c32a52e 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -68,7 +68,7 @@
   String toString() => element.toString();
   List<Constant> getDependencies() => const <Constant>[];
   DartString toDartString() {
-    return new DartString.literal(element.name.slowToString());
+    return new DartString.literal(element.name);
   }
 
   DartType computeType(Compiler compiler) {
@@ -391,18 +391,15 @@
       const LiteralDartString("__proto__");
 
   /** The dart class implementing constant map literals. */
-  static const SourceString DART_CLASS = const SourceString("ConstantMap");
-  static const SourceString DART_STRING_CLASS =
-      const SourceString("ConstantStringMap");
-  static const SourceString DART_PROTO_CLASS =
-      const SourceString("ConstantProtoMap");
-  static const SourceString DART_GENERAL_CLASS =
-      const SourceString("GeneralConstantMap");
-  static const SourceString LENGTH_NAME = const SourceString("length");
-  static const SourceString JS_OBJECT_NAME = const SourceString("_jsObject");
-  static const SourceString KEYS_NAME = const SourceString("_keys");
-  static const SourceString PROTO_VALUE = const SourceString("_protoValue");
-  static const SourceString JS_DATA_NAME = const SourceString("_jsData");
+  static const String DART_CLASS = "ConstantMap";
+  static const String DART_STRING_CLASS = "ConstantStringMap";
+  static const String DART_PROTO_CLASS = "ConstantProtoMap";
+  static const String DART_GENERAL_CLASS = "GeneralConstantMap";
+  static const String LENGTH_NAME = "length";
+  static const String JS_OBJECT_NAME = "_jsObject";
+  static const String KEYS_NAME = "_keys";
+  static const String PROTO_VALUE = "_protoValue";
+  static const String JS_DATA_NAME = "_jsData";
 
   final ListConstant keys;
   final List<Constant> values;
@@ -554,7 +551,7 @@
     int i = 0;
     fieldElements.forEach((Element field, Constant value) {
       if (i > 0) sb.write(',');
-      sb.write(Error.safeToString(field.name.slowToString()));
+      sb.write(Error.safeToString(field.name));
       sb.write('=');
       sb.write(Error.safeToString(value));
       i++;
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index e64821a..e30543a 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -110,7 +110,7 @@
   bool analyzeOnly = false;
   bool hasDisallowUnsafeEval = false;
   // TODO(johnniwinther): Measure time for reading files.
-  SourceFileProvider inputProvider = new SourceFileProvider();
+  SourceFileProvider inputProvider = new CompilerSourceFileProvider();
   diagnosticHandler = new FormattingDiagnosticHandler(inputProvider);
 
   passThrough(String argument) => options.add(argument);
diff --git a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
index 6867b08f..6499365 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
@@ -25,6 +25,7 @@
 import 'tree/tree.dart';
 import 'universe/universe.dart';
 import 'util/util.dart';
+import 'util/characters.dart' show $_;
 import '../compiler.dart' as api;
 import 'patch_parser.dart';
 import 'types/types.dart' as ti;
@@ -35,8 +36,7 @@
 import 'mirrors_used.dart' show MirrorUsageAnalyzerTask;
 
 export 'resolution/resolution.dart' show TreeElements, TreeElementMapping;
-export 'scanner/scannerlib.dart' show SourceString,
-                                      isUserDefinableOperator,
+export 'scanner/scannerlib.dart' show isUserDefinableOperator,
                                       isUnaryOperator,
                                       isBinaryOperator,
                                       isTernaryOperator,
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index bbf3c20..4168c72 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -162,7 +162,7 @@
         classMembers.keys.map((classElement) => classElement.thisType));
     workQueue.addAll(compiler.resolverWorld.isChecks);
     Element typeErrorElement =
-        compiler.coreLibrary.find(new SourceString('TypeError'));
+        compiler.coreLibrary.find('TypeError');
     DartType typeErrorType = typeErrorElement.computeType(compiler);
     if (workQueue.indexOf(typeErrorType) != -1) {
       return false;
@@ -208,19 +208,19 @@
     ];
     final coreLibrary = compiler.coreLibrary;
     for (final name in LITERAL_TYPE_NAMES) {
-      ClassElement classElement = coreLibrary.findLocal(new SourceString(name));
+      ClassElement classElement = coreLibrary.findLocal(name);
       classElement.ensureResolved(compiler);
     }
     // Enqueue the methods that the VM might invoke on user objects because
     // we don't trust the resolution to always get these included.
     world.registerInvocation(
-        new Selector.call(const SourceString("toString"), null, 0));
+        new Selector.call("toString", null, 0));
     world.registerInvokedGetter(
-        new Selector.getter(const SourceString("hashCode"), null));
+        new Selector.getter("hashCode", null));
     world.registerInvocation(
-        new Selector.binaryOperator(const SourceString("==")));
+        new Selector.binaryOperator("=="));
     world.registerInvocation(
-        new Selector.call(const SourceString("compareTo"), null, 1));
+        new Selector.call("compareTo", null, 1));
   }
 
   void codegen(CodegenWorkItem work) { }
@@ -251,7 +251,7 @@
           // members.
           element.parseNode(compiler);
           classElement.forEachLocalMember((member) {
-            final name = member.name.slowToString();
+            final name = member.name;
             // Skip operator names.
             if (!name.startsWith(r'operator$')) {
               // Fetch name of named constructors and factories if any,
@@ -265,7 +265,7 @@
         // if one imports dart:core with a prefix, we cannot tell prefix.name
         // from dynamic invocation (alas!).  So we'd better err on preserving
         // those names.
-        fixedMemberNames.add(element.name.slowToString());
+        fixedMemberNames.add(element.name);
       });
     }
     // As of now names of named optionals are not renamed. Therefore add all
@@ -276,7 +276,7 @@
           element.computeSignature(compiler).optionalParameters;
       for (final optional in optionalParameters) {
         if (optional.kind != ElementKind.FIELD_PARAMETER) continue;
-        fixedMemberNames.add(optional.name.slowToString());
+        fixedMemberNames.add(optional.name);
       }
     }
     // The VM will automatically invoke the call method of objects
@@ -381,8 +381,8 @@
     // Add synthesized constructors to classes with no resolved constructors,
     // but which originally had any constructor.  That should prevent
     // those classes from being instantiable with default constructor.
-    Identifier synthesizedIdentifier =
-        new Identifier(new StringToken(IDENTIFIER_INFO, '', -1));
+    Identifier synthesizedIdentifier = new Identifier(
+        new StringToken.fromString(IDENTIFIER_INFO, '', -1));
 
     NextClassElement:
     for (ClassElement classElement in classMembers.keys) {
@@ -403,15 +403,16 @@
           compiler.types.voidType,
           const Link<DartType>(),
           const Link<DartType>(),
-          const Link<SourceString>(),
+          const Link<String>(),
           const Link<DartType>()
           );
       constructor.cachedNode = new FunctionExpression(
           new Send(classNode.name, synthesizedIdentifier),
-          new NodeList(new StringToken(OPEN_PAREN_INFO, '(', -1),
+          new NodeList(new StringToken.fromString(OPEN_PAREN_INFO, '(', -1),
                        const Link<Node>(),
-                       new StringToken(CLOSE_PAREN_INFO, ')', -1)),
-          new EmptyStatement(new StringToken(SEMICOLON_INFO, ';', -1)),
+                       new StringToken.fromString(CLOSE_PAREN_INFO, ')', -1)),
+          new EmptyStatement(
+              new StringToken.fromString(SEMICOLON_INFO, ';', -1)),
           null, Modifiers.EMPTY, null, null);
 
       if (!constructor.isSynthesized) {
@@ -506,7 +507,7 @@
     int nonPlatformSize = 0;
     for (LibraryElement lib in referencedLibraries) {
       for (CompilationUnitElement compilationUnit in lib.compilationUnits) {
-        nonPlatformSize += compilationUnit.script.text.length;
+        nonPlatformSize += compilationUnit.script.file.length;
       }
     }
     int percentage = compiler.assembledCode.length * 100 ~/ nonPlatformSize;
@@ -523,9 +524,9 @@
           then((LibraryElement element) {
         mirrorHelperLibrary = element;
         mirrorHelperGetNameFunction = mirrorHelperLibrary.find(
-            const SourceString(MirrorRenamer.MIRROR_HELPER_GET_NAME_FUNCTION));
+            MirrorRenamer.MIRROR_HELPER_GET_NAME_FUNCTION);
         mirrorHelperSymbolsMap = mirrorHelperLibrary.find(
-            const SourceString(MirrorRenamer.MIRROR_HELPER_SYMBOLS_MAP_NAME));
+            MirrorRenamer.MIRROR_HELPER_SYMBOLS_MAP_NAME);
       });
     }
     return new Future.value();
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index 6f07e12..1deab48 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -20,7 +20,7 @@
       : parameterIdentifiers = new Set<String>(),
       localPlaceholders = new Set<LocalPlaceholder>();
   void registerParameter(Identifier node) {
-    parameterIdentifiers.add(node.source.slowToString());
+    parameterIdentifiers.add(node.source);
   }
 }
 
@@ -264,7 +264,7 @@
 
     // TODO(smok): Maybe we should rename privates as well, their privacy
     // should not matter if they are local vars.
-    if (node.source.isPrivate()) return;
+    if (isPrivateName(node.source)) return;
     if (element.isParameter() && !isTypedefParameter(element) &&
         isNamedOptionalParameter()) {
       currentFunctionScope.registerParameter(node);
@@ -275,9 +275,9 @@
 
   void tryMakeMemberPlaceholder(Identifier node) {
     assert(node != null);
-    if (node.source.isPrivate()) return;
+    if (isPrivateName(node.source)) return;
     if (node is Operator) return;
-    final identifier = node.source.slowToString();
+    final identifier = node.source;
     if (fixedMemberNames.contains(identifier)) return;
     memberPlaceholders.putIfAbsent(
         identifier, () => new Set<Identifier>()).add(node);
@@ -343,7 +343,7 @@
 
   void makeLocalPlaceholder(Identifier identifier) {
     LocalPlaceholder getLocalPlaceholder() {
-      String name = identifier.source.slowToString();
+      String name = identifier.source;
       return currentLocalPlaceholders.putIfAbsent(name, () {
         LocalPlaceholder localPlaceholder = new LocalPlaceholder(name);
         currentFunctionScope.localPlaceholders.add(localPlaceholder);
@@ -399,10 +399,10 @@
         NamedArgument named = argument.asNamedArgument();
         if (named == null) continue;
         Identifier name = named.name;
-        String nameAsString = name.source.slowToString();
+        String nameAsString = name.source;
         for (final parameter in optionalParameters) {
           if (identical(parameter.kind, ElementKind.FIELD_PARAMETER)) {
-            if (parameter.name.slowToString() == nameAsString) {
+            if (parameter.name == nameAsString) {
               tryMakeMemberPlaceholder(name);
               break;
             }
@@ -457,7 +457,7 @@
   }
 
   visitIdentifier(Identifier identifier) {
-    if (identifier.source.isPrivate()) makePrivateIdentifier(identifier);
+    if (isPrivateName(identifier.source)) makePrivateIdentifier(identifier);
   }
 
   static bool isPlainTypeName(TypeAnnotation typeAnnotation) {
@@ -469,7 +469,7 @@
 
   static bool isDynamicType(TypeAnnotation typeAnnotation) {
     if (!isPlainTypeName(typeAnnotation)) return false;
-    String name = typeAnnotation.typeName.asIdentifier().source.slowToString();
+    String name = typeAnnotation.typeName.asIdentifier().source;
     return name == 'dynamic';
   }
 
@@ -548,7 +548,7 @@
 
   visitFunctionExpression(FunctionExpression node) {
     bool isKeyword(Identifier id) =>
-        id != null && Keyword.keywords[id.source.slowToString()] != null;
+        id != null && Keyword.keywords[id.source] != null;
 
     Element element = treeElements[node];
     // May get null here in case of A(int this.f());
@@ -610,7 +610,7 @@
     // Another poor man type resolution.
     // Find this variable in enclosing type declaration parameters.
     for (DartType type in typeDeclaration.typeVariables) {
-      if (type.name.slowToString() == name.source.slowToString()) {
+      if (type.name == name.source) {
         makeTypePlaceholder(name, type);
         return true;
       }
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
index bcaa080..2158855 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
@@ -109,8 +109,8 @@
       Function renameString, Function renameElement) {
     assert(element.isConstructor());
     StringBuffer result = new StringBuffer();
-    String name = element.name.slowToString();
-    if (element.name != const SourceString('')) {
+    String name = element.name;
+    if (element.name != '') {
       // Named constructor or factory. Is there a more reliable way to check
       // this case?
       if (!placeholder.isRedirectingCall) {
@@ -133,7 +133,7 @@
            Elements.isStaticOrTopLevel(element) ||
            element is TypeVariableElement);
     // TODO(smok): We may want to reuse class static field and method names.
-    String originalName = element.name.slowToString();
+    String originalName = element.name;
     LibraryElement library = element.getLibrary();
     if (identical(element.getLibrary(), compiler.coreLibrary)) {
       return originalName;
@@ -257,7 +257,7 @@
       if (functionElement.getEnclosingClass() != null) {
         functionElement.getEnclosingClass().forEachMember(
             (enclosingClass, member) {
-              memberIdentifiers.add(member.name.slowToString());
+              memberIdentifiers.add(member.name);
             });
       }
       Set<String> usedLocalIdentifiers = new Set<String>();
@@ -293,7 +293,7 @@
         }
   });
   sortedForEach(placeholderCollector.privateNodes, (library, nodes) {
-    renameNodes(nodes, (node) => rename(library, node.source.slowToString()));
+    renameNodes(nodes, (node) => rename(library, node.source));
   });
   renameNodes(placeholderCollector.unresolvedNodes,
       (_) => generateUniqueName('Unresolved'));
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index d8487c95..78a6490 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -8,7 +8,6 @@
 import 'elements/modelx.dart'
     show VoidElementX, LibraryElementX, BaseClassElementX;
 import 'elements/elements.dart';
-import 'scanner/scannerlib.dart' show SourceString;
 import 'util/util.dart' show Link, LinkBuilder;
 
 class TypeKind {
@@ -28,7 +27,7 @@
 }
 
 abstract class DartType {
-  SourceString get name;
+  String get name;
 
   TypeKind get kind;
 
@@ -155,7 +154,7 @@
 
   TypeKind get kind => TypeKind.TYPE_VARIABLE;
 
-  SourceString get name => element.name;
+  String get name => element.name;
 
   DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
     if (parameters.isEmpty) {
@@ -199,7 +198,7 @@
     return identical(other.element, element);
   }
 
-  String toString() => name.slowToString();
+  String toString() => name;
 }
 
 /**
@@ -212,7 +211,7 @@
 
   TypeKind get kind => TypeKind.STATEMENT;
 
-  SourceString get name => new SourceString(stringName);
+  String get name => stringName;
 
   const StatementType(this.stringName);
 
@@ -251,7 +250,7 @@
 
   TypeKind get kind => TypeKind.VOID;
 
-  SourceString get name => element.name;
+  String get name => element.name;
 
   final Element element;
 
@@ -272,7 +271,7 @@
 
   bool operator ==(other) => other is VoidType;
 
-  String toString() => name.slowToString();
+  String toString() => name;
 }
 
 class MalformedType extends DartType {
@@ -306,7 +305,7 @@
 
   TypeKind get kind => TypeKind.MALFORMED_TYPE;
 
-  SourceString get name => element.name;
+  String get name => element.name;
 
   DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
     // Malformed types are not substitutable.
@@ -326,9 +325,9 @@
     var sb = new StringBuffer();
     if (typeArguments != null) {
       if (userProvidedBadType != null) {
-        sb.write(userProvidedBadType.name.slowToString());
+        sb.write(userProvidedBadType.name);
       } else {
-        sb.write(element.name.slowToString());
+        sb.write(element.name);
       }
       if (!typeArguments.isEmpty) {
         sb.write('<');
@@ -387,7 +386,7 @@
 
   String toString() {
     StringBuffer sb = new StringBuffer();
-    sb.write(name.slowToString());
+    sb.write(name);
     if (!isRaw) {
       sb.write('<');
       typeArguments.printOn(sb, ', ');
@@ -447,7 +446,7 @@
 
   TypeKind get kind => TypeKind.INTERFACE;
 
-  SourceString get name => element.name;
+  String get name => element.name;
 
   InterfaceType _createType(Link<DartType> newTypeArguments) {
     return new InterfaceType(element, newTypeArguments);
@@ -478,7 +477,7 @@
    * Finds the method, field or property named [name] declared or inherited
    * on this interface type.
    */
-  Member lookupMember(SourceString name, {bool isSetter: false}) {
+  Member lookupMember(String name, {bool isSetter: false}) {
     // Abstract field returned when setter was needed but only a getter was
     // present and vice-versa.
     Member fallbackAbstractField;
@@ -588,7 +587,7 @@
   /**
    * The names of the named parameters ordered lexicographically.
    */
-  final Link<SourceString> namedParameters;
+  final Link<String> namedParameters;
 
   /**
    * The types of the named parameters in the order corresponding to the
@@ -600,7 +599,7 @@
                DartType this.returnType,
                Link<DartType> this.parameterTypes,
                Link<DartType> this.optionalParameterTypes,
-               Link<SourceString> this.namedParameters,
+               Link<String> this.namedParameters,
                Link<DartType> this.namedParameterTypes) {
     assert(invariant(element, element.isDeclaration));
     // Assert that optional and named parameters are not used at the same time.
@@ -610,8 +609,8 @@
 
   TypeKind get kind => TypeKind.FUNCTION;
 
-  DartType getNamedParameterType(SourceString name) {
-    Link<SourceString> namedParameter = namedParameters;
+  DartType getNamedParameterType(String name) {
+    Link<String> namedParameter = namedParameters;
     Link<DartType> namedParameterType = namedParameterTypes;
     while (!namedParameter.isEmpty && !namedParameterType.isEmpty) {
       if (namedParameter.head == name) {
@@ -700,7 +699,7 @@
         sb.write(', ');
       }
       sb.write('{');
-      Link<SourceString> namedParameter = namedParameters;
+      Link<String> namedParameter = namedParameters;
       Link<DartType> namedParameterType = namedParameterTypes;
       first = true;
       while (!namedParameter.isEmpty && !namedParameterType.isEmpty) {
@@ -709,7 +708,7 @@
         }
         sb.write(namedParameterType.head);
         sb.write(' ');
-          sb.write(namedParameter.head.slowToString());
+          sb.write(namedParameter.head);
         namedParameter = namedParameter.tail;
         namedParameterType = namedParameterType.tail;
         first = false;
@@ -720,7 +719,7 @@
     return sb.toString();
   }
 
-  SourceString get name => const SourceString('Function');
+  String get name => 'Function';
 
   int computeArity() {
     int arity = 0;
@@ -736,7 +735,7 @@
     for (DartType parameter  in optionalParameterTypes) {
       hash = 19 * hash + 7 * parameter.hashCode;
     }
-    for (SourceString name  in namedParameters) {
+    for (String name  in namedParameters) {
       hash = 23 * hash + 11 * name.hashCode;
     }
     for (DartType parameter  in namedParameterTypes) {
@@ -775,11 +774,12 @@
 
   TypeKind get kind => TypeKind.TYPEDEF;
 
-  SourceString get name => element.name;
+  String get name => element.name;
 
   DartType unalias(Compiler compiler) {
     // TODO(ahe): This should be [ensureResolved].
     compiler.resolveTypedef(element);
+    element.checkCyclicReference(compiler);
     DartType definition = element.alias.unalias(compiler);
     TypedefType declaration = element.computeType(compiler);
     return definition.subst(typeArguments, declaration.typeArguments);
@@ -801,7 +801,7 @@
 class DynamicType extends InterfaceType {
   DynamicType(ClassElement element) : super(element);
 
-  SourceString get name => const SourceString('dynamic');
+  String get name => 'dynamic';
 
   bool get treatAsDynamic => true;
 
@@ -884,7 +884,7 @@
   }
 
   String toString() {
-    return '$receiver.${element.name.slowToString()}';
+    return '$receiver.${element.name}';
   }
 }
 
@@ -1017,9 +1017,9 @@
       // Since named parameters are globally ordered we can determine the
       // subset relation with a linear search for [:sf.namedParameters:]
       // within [:tf.namedParameters:].
-      Link<SourceString> tNames = tf.namedParameters;
+      Link<String> tNames = tf.namedParameters;
       Link<DartType> tTypes = tf.namedParameterTypes;
-      Link<SourceString> sNames = sf.namedParameters;
+      Link<String> sNames = sf.namedParameters;
       Link<DartType> sTypes = sf.namedParameterTypes;
       while (!tNames.isEmpty && !sNames.isEmpty) {
         if (sNames.head == tNames.head) {
@@ -1354,11 +1354,10 @@
         result = compareList(aFunc.optionalParameterTypes,
                              bFunc.optionalParameterTypes);
         if (result != 0) return result;
-        Link<SourceString> aNames = aFunc.namedParameters;
-        Link<SourceString> bNames = bFunc.namedParameters;
+        Link<String> aNames = aFunc.namedParameters;
+        Link<String> bNames = bFunc.namedParameters;
         while (!aNames.isEmpty && !bNames.isEmpty) {
-          int result = aNames.head.slowToString().compareTo(
-                       bNames.head.slowToString());
+          int result = aNames.head.compareTo(bNames.head);
           if (result != 0) return result;
           aNames = aNames.tail;
           bNames = bNames.tail;
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index cf17934..1a182f7 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -9,7 +9,6 @@
             CompilerTask,
             ConstructedConstant,
             MessageKind,
-            SourceString,
             StringConstant;
 
 import 'elements/elements.dart'
@@ -199,17 +198,15 @@
         if (element == deferredLibraryClass) {
           ConstructedConstant value = metadata.value;
           StringConstant nameField = value.fields[0];
-          SourceString expectedName = nameField.toDartString().source;
+          String expectedName = nameField.toDartString().slowToString();
           LibraryElement deferredLibrary = library.getLibraryFromTag(tag);
           link = link.prepend(deferredLibrary);
-          SourceString actualName =
-              new SourceString(deferredLibrary.getLibraryOrScriptName());
+          String actualName = deferredLibrary.getLibraryOrScriptName();
           if (expectedName != actualName) {
             compiler.reportError(
                 metadata,
                 MessageKind.DEFERRED_LIBRARY_NAME_MISMATCH,
-                { 'expectedName': expectedName.slowToString(),
-                  'actualName': actualName.slowToString()});
+                { 'expectedName': expectedName, 'actualName': actualName });
           }
         }
       }
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index 6485e7d..8d2bba5 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -18,7 +18,6 @@
                                  DiagnosticListener,
                                  Script,
                                  FunctionType,
-                                 SourceString,
                                  Selector,
                                  Constant,
                                  Compiler;
@@ -170,7 +169,7 @@
  * It is better to keep such state in a table on the side.
  */
 abstract class Element implements Spannable {
-  SourceString get name;
+  String get name;
   ElementKind get kind;
   Modifiers get modifiers;
   Element get enclosingElement;
@@ -372,21 +371,21 @@
     return isLocal(element);
   }
 
-  static SourceString reconstructConstructorNameSourceString(Element element) {
-    if (element.name == const SourceString('')) {
+  static String reconstructConstructorNameSourceString(Element element) {
+    if (element.name == '') {
       return element.getEnclosingClass().name;
     } else {
-      return new SourceString(reconstructConstructorName(element));
+      return reconstructConstructorName(element);
     }
   }
 
   // TODO(johnniwinther): Remove this method.
   static String reconstructConstructorName(Element element) {
-    String className = element.getEnclosingClass().name.slowToString();
-    if (element.name == const SourceString('')) {
+    String className = element.getEnclosingClass().name;
+    if (element.name == '') {
       return className;
     } else {
-      return '$className\$${element.name.slowToString()}';
+      return '$className\$${element.name}';
     }
   }
 
@@ -399,112 +398,106 @@
    * JavaScript identifers, except it may include reserved words for
    * non-operator names.
    */
-  static SourceString operatorNameToIdentifier(SourceString name) {
-    if (name == null) return null;
-    String value = name.stringValue;
-    if (value == null) {
+  static String operatorNameToIdentifier(String name) {
+    if (name == null) {
       return name;
-    } else if (identical(value, '==')) {
-      return const SourceString(r'operator$eq');
-    } else if (identical(value, '~')) {
-      return const SourceString(r'operator$not');
-    } else if (identical(value, '[]')) {
-      return const SourceString(r'operator$index');
-    } else if (identical(value, '[]=')) {
-      return const SourceString(r'operator$indexSet');
-    } else if (identical(value, '*')) {
-      return const SourceString(r'operator$mul');
-    } else if (identical(value, '/')) {
-      return const SourceString(r'operator$div');
-    } else if (identical(value, '%')) {
-      return const SourceString(r'operator$mod');
-    } else if (identical(value, '~/')) {
-      return const SourceString(r'operator$tdiv');
-    } else if (identical(value, '+')) {
-      return const SourceString(r'operator$add');
-    } else if (identical(value, '<<')) {
-      return const SourceString(r'operator$shl');
-    } else if (identical(value, '>>')) {
-      return const SourceString(r'operator$shr');
-    } else if (identical(value, '>=')) {
-      return const SourceString(r'operator$ge');
-    } else if (identical(value, '>')) {
-      return const SourceString(r'operator$gt');
-    } else if (identical(value, '<=')) {
-      return const SourceString(r'operator$le');
-    } else if (identical(value, '<')) {
-      return const SourceString(r'operator$lt');
-    } else if (identical(value, '&')) {
-      return const SourceString(r'operator$and');
-    } else if (identical(value, '^')) {
-      return const SourceString(r'operator$xor');
-    } else if (identical(value, '|')) {
-      return const SourceString(r'operator$or');
-    } else if (identical(value, '-')) {
-      return const SourceString(r'operator$sub');
-    } else if (identical(value, 'unary-')) {
-      return const SourceString(r'operator$negate');
+    } else if (identical(name, '==')) {
+      return r'operator$eq';
+    } else if (identical(name, '~')) {
+      return r'operator$not';
+    } else if (identical(name, '[]')) {
+      return r'operator$index';
+    } else if (identical(name, '[]=')) {
+      return r'operator$indexSet';
+    } else if (identical(name, '*')) {
+      return r'operator$mul';
+    } else if (identical(name, '/')) {
+      return r'operator$div';
+    } else if (identical(name, '%')) {
+      return r'operator$mod';
+    } else if (identical(name, '~/')) {
+      return r'operator$tdiv';
+    } else if (identical(name, '+')) {
+      return r'operator$add';
+    } else if (identical(name, '<<')) {
+      return r'operator$shl';
+    } else if (identical(name, '>>')) {
+      return r'operator$shr';
+    } else if (identical(name, '>=')) {
+      return r'operator$ge';
+    } else if (identical(name, '>')) {
+      return r'operator$gt';
+    } else if (identical(name, '<=')) {
+      return r'operator$le';
+    } else if (identical(name, '<')) {
+      return r'operator$lt';
+    } else if (identical(name, '&')) {
+      return r'operator$and';
+    } else if (identical(name, '^')) {
+      return r'operator$xor';
+    } else if (identical(name, '|')) {
+      return r'operator$or';
+    } else if (identical(name, '-')) {
+      return r'operator$sub';
+    } else if (identical(name, 'unary-')) {
+      return r'operator$negate';
     } else {
       return name;
     }
   }
 
-  static SourceString constructOperatorNameOrNull(SourceString op,
-                                                  bool isUnary) {
-    String value = op.stringValue;
-    if (isMinusOperator(value)) {
-      return isUnary ? const SourceString('unary-') : op;
-    } else if (isUserDefinableOperator(value)) {
+  static String constructOperatorNameOrNull(String op, bool isUnary) {
+    if (isMinusOperator(op)) {
+      return isUnary ? 'unary-' : op;
+    } else if (isUserDefinableOperator(op)) {
       return op;
     } else {
       return null;
     }
   }
 
-  static SourceString constructOperatorName(SourceString op, bool isUnary) {
-    SourceString operatorName = constructOperatorNameOrNull(op, isUnary);
-    if (operatorName == null) throw 'Unhandled operator: ${op.slowToString()}';
+  static String constructOperatorName(String op, bool isUnary) {
+    String operatorName = constructOperatorNameOrNull(op, isUnary);
+    if (operatorName == null) throw 'Unhandled operator: $op';
     else return operatorName;
   }
 
-  static SourceString mapToUserOperatorOrNull(SourceString op) {
-    String value = op.stringValue;
-
-    if (identical(value, '!=')) return const SourceString('==');
-    if (identical(value, '*=')) return const SourceString('*');
-    if (identical(value, '/=')) return const SourceString('/');
-    if (identical(value, '%=')) return const SourceString('%');
-    if (identical(value, '~/=')) return const SourceString('~/');
-    if (identical(value, '+=')) return const SourceString('+');
-    if (identical(value, '-=')) return const SourceString('-');
-    if (identical(value, '<<=')) return const SourceString('<<');
-    if (identical(value, '>>=')) return const SourceString('>>');
-    if (identical(value, '&=')) return const SourceString('&');
-    if (identical(value, '^=')) return const SourceString('^');
-    if (identical(value, '|=')) return const SourceString('|');
+  static String mapToUserOperatorOrNull(String op) {
+    if (identical(op, '!=')) return '==';
+    if (identical(op, '*=')) return '*';
+    if (identical(op, '/=')) return '/';
+    if (identical(op, '%=')) return '%';
+    if (identical(op, '~/=')) return '~/';
+    if (identical(op, '+=')) return '+';
+    if (identical(op, '-=')) return '-';
+    if (identical(op, '<<=')) return '<<';
+    if (identical(op, '>>=')) return '>>';
+    if (identical(op, '&=')) return '&';
+    if (identical(op, '^=')) return '^';
+    if (identical(op, '|=')) return '|';
 
     return null;
   }
 
-  static SourceString mapToUserOperator(SourceString op) {
-    SourceString userOperator = mapToUserOperatorOrNull(op);
-    if (userOperator == null) throw 'Unhandled operator: ${op.slowToString()}';
+  static String mapToUserOperator(String op) {
+    String userOperator = mapToUserOperatorOrNull(op);
+    if (userOperator == null) throw 'Unhandled operator: $op';
     else return userOperator;
   }
 
   static bool isNumberOrStringSupertype(Element element, Compiler compiler) {
     LibraryElement coreLibrary = compiler.coreLibrary;
-    return (element == coreLibrary.find(const SourceString('Comparable')));
+    return (element == coreLibrary.find('Comparable'));
   }
 
   static bool isStringOnlySupertype(Element element, Compiler compiler) {
     LibraryElement coreLibrary = compiler.coreLibrary;
-    return element == coreLibrary.find(const SourceString('Pattern'));
+    return element == coreLibrary.find('Pattern');
   }
 
   static bool isListSupertype(Element element, Compiler compiler) {
     LibraryElement coreLibrary = compiler.coreLibrary;
-    return element == coreLibrary.find(const SourceString('Iterable'));
+    return element == coreLibrary.find('Iterable');
   }
 
   /// A `compareTo` function that places [Element]s in a consistent order based
@@ -521,7 +514,7 @@
     int offsetB = positionB == null ? -1 : positionB.charOffset;
     r = offsetA.compareTo(offsetB);
     if (r != 0) return r;
-    r = a.name.slowToString().compareTo(b.name.slowToString());
+    r = a.name.compareTo(b.name);
     if (r != 0) return r;
     // Same file, position and name.  If this happens, we should find out why
     // and make the order total and independent of hashCode.
@@ -619,7 +612,7 @@
 // TODO(kasperl): This probably shouldn't be called an element. It's
 // just an interface shared by classes and libraries.
 abstract class ScopeContainerElement implements Element {
-  Element localLookup(SourceString elementName);
+  Element localLookup(String elementName);
 
   void forEachLocalMember(f(Element element));
 }
@@ -689,8 +682,8 @@
 
   void setExports(Iterable<Element> exportedElements);
 
-  Element find(SourceString elementName);
-  Element findLocal(SourceString elementName);
+  Element find(String elementName);
+  Element findLocal(String elementName);
   void forEachExport(f(Element element));
 
   bool hasLibraryName();
@@ -701,7 +694,7 @@
 
 abstract class PrefixElement extends Element {
   void addImport(Element element, Import import, DiagnosticListener listener);
-  Element lookupLocalMember(SourceString memberName);
+  Element lookupLocalMember(String memberName);
 }
 
 abstract class TypedefElement extends Element
@@ -717,6 +710,8 @@
   // TODO(kasperl): Try to get rid of these setters.
   void set alias(DartType value);
   void set functionSignature(FunctionSignature value);
+
+  void checkCyclicReference(Compiler compiler);
 }
 
 abstract class VariableElement extends Element {
@@ -852,7 +847,7 @@
   int get supertypeLoadState;
   int get resolutionState;
   bool get isResolved;
-  SourceString get nativeTagInfo;
+  String get nativeTagInfo;
 
   bool get isMixinApplication;
   bool get isUnnamedMixinApplication;
@@ -868,7 +863,7 @@
   void set origin(ClassElement value);
   void set supertypeLoadState(int value);
   void set resolutionState(int value);
-  void set nativeTagInfo(SourceString value);
+  void set nativeTagInfo(String value);
 
   bool isObject(Compiler compiler);
   bool isSubclassOf(ClassElement cls);
@@ -885,18 +880,18 @@
   void addBackendMember(Element element);
   void reverseBackendMembers();
 
-  Element lookupMember(SourceString memberName);
+  Element lookupMember(String memberName);
   Element lookupSelector(Selector selector, Compiler compiler);
   Element lookupSuperSelector(Selector selector, Compiler compiler);
 
-  Element lookupLocalMember(SourceString memberName);
-  Element lookupBackendMember(SourceString memberName);
-  Element lookupSuperMember(SourceString memberName);
+  Element lookupLocalMember(String memberName);
+  Element lookupBackendMember(String memberName);
+  Element lookupSuperMember(String memberName);
 
-  Element lookupSuperMemberInLibrary(SourceString memberName,
+  Element lookupSuperMemberInLibrary(String memberName,
                                      LibraryElement library);
 
-  Element lookupSuperInterfaceMember(SourceString memberName,
+  Element lookupSuperInterfaceMember(String memberName,
                                      LibraryElement fromLibrary);
 
   Element validateConstructorLookupResults(Selector selector,
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index fccf1bf..b7d6f5e 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -20,10 +20,10 @@
                                  DiagnosticListener,
                                  Script,
                                  FunctionType,
-                                 SourceString,
                                  Selector,
                                  Constant,
-                                 Compiler;
+                                 Compiler,
+                                 isPrivateName;
 
 import '../dart_types.dart';
 
@@ -33,7 +33,7 @@
 class ElementX implements Element {
   static int elementHashCode = 0;
 
-  final SourceString name;
+  final String name;
   final ElementKind kind;
   final Element enclosingElement;
   final int hashCode = ++elementHashCode;
@@ -182,7 +182,7 @@
     // For constructors, that doesn't work because they may have
     // named formed out of multiple tokens (named constructors) so
     // for those we search for the class name instead.
-    SourceString needle = isConstructor() ? enclosingElement.name : name;
+    String needle = isConstructor() ? enclosingElement.name : name;
     for (Token t = token; EOF_TOKEN != t.kind; t = t.next) {
       if (needle == t.value) return t;
     }
@@ -250,10 +250,10 @@
   String toString() {
     // TODO(johnniwinther): Test for nullness of name, or make non-nullness an
     // invariant for all element types?
-    var nameText = name != null ? name.slowToString() : '?';
+    var nameText = name != null ? name : '?';
     if (enclosingElement != null && !isTopLevel()) {
       String holderName = enclosingElement.name != null
-          ? enclosingElement.name.slowToString()
+          ? enclosingElement.name
           : '${enclosingElement.kind}?';
       return '$kind($holderName#${nameText})';
     } else {
@@ -309,7 +309,7 @@
   final Map messageArguments;
 
   ErroneousElementX(this.messageKind, this.messageArguments,
-                    SourceString name, Element enclosing)
+                    String name, Element enclosing)
       : super(name, ElementKind.ERROR, enclosing);
 
   isErroneous() => true;
@@ -346,8 +346,7 @@
   computeTargetType(Compiler compiler, InterfaceType newType) => unsupported();
 
   String toString() {
-    String n = name.slowToString();
-    return '<$n: ${messageKind.message(messageArguments)}>';
+    return '<$name: ${messageKind.message(messageArguments)}>';
   }
 }
 
@@ -447,9 +446,9 @@
 
   bool isAmbiguous() => true;
 
-  Set flatten() {
+  Setlet flatten() {
     Element element = this;
-    var set = new Set();
+    var set = new Setlet();
     while (element.isAmbiguous()) {
       AmbiguousElement ambiguous = element;
       set.add(ambiguous.newElement);
@@ -460,14 +459,14 @@
   }
 
   void diagnose(Element context, DiagnosticListener listener) {
-    Set ambiguousElements = flatten();
+    Setlet ambiguousElements = flatten();
     MessageKind code = (ambiguousElements.length == 1)
         ? MessageKind.AMBIGUOUS_REEXPORT : MessageKind.AMBIGUOUS_LOCATION;
     LibraryElementX importer = context.getLibrary();
     for (Element element in ambiguousElements) {
       var arguments = {'name': element.name};
       listener.reportInfo(element, code, arguments);
-      Link<Import> importers = importer.importers[element];
+      Link<Import> importers = importer.importers.getImports(element);
       listener.withCurrentElement(importer, () {
         for (; !importers.isEmpty; importers = importers.tail) {
           listener.reportInfo(
@@ -479,17 +478,17 @@
 }
 
 class ScopeX {
-  final Map<SourceString, Element> contents = new Map<SourceString, Element>();
+  final Map<String, Element> contents = new Map<String, Element>();
 
   bool get isEmpty => contents.isEmpty;
   Iterable<Element> get values => contents.values;
 
-  Element lookup(SourceString name) {
+  Element lookup(String name) {
     return contents[name];
   }
 
   void add(Element element, DiagnosticListener listener) {
-    SourceString name = element.name;
+    String name = element.name;
     if (element.isAccessor()) {
       addAccessor(element, contents[name], listener);
     } else {
@@ -523,7 +522,7 @@
                    DiagnosticListener listener) {
     void reportError(Element other) {
       // TODO(ahe): Do something similar to Resolver.reportErrorWithContext.
-      listener.cancel('duplicate definition of ${accessor.name.slowToString()}',
+      listener.cancel('duplicate definition of ${accessor.name}',
                       element: accessor);
       listener.cancel('existing definition', element: other);
     }
@@ -568,7 +567,7 @@
 
   CompilationUnitElementX(Script script, LibraryElement library)
     : this.script = script,
-      super(new SourceString(script.name),
+      super(script.name,
             ElementKind.COMPILATION_UNIT,
             library) {
     library.addCompilationUnit(this);
@@ -632,6 +631,25 @@
   }
 }
 
+class Importers {
+  Map<Element, Link<Import>> importers = new Map<Element, Link<Import>>();
+
+  Link<Import> getImports(Element element) {
+    Link<Import> imports = importers[element];
+    return imports != null ? imports : const Link<Import>();
+  }
+
+  Import getImport(Element element) => getImports(element).head;
+
+  void registerImport(Element element, Import import) {
+    if (import == null) return;
+
+    importers[element] =
+        importers.putIfAbsent(element, () => const Link<Import>())
+          .prepend(import);
+  }
+}
+
 class ImportScope {
   /**
    * Map for elements imported through import declarations.
@@ -639,8 +657,8 @@
    * Addition to the map is performed by [addImport]. Lookup is done trough
    * [find].
    */
-  final Map<SourceString, Element> importScope =
-      new Map<SourceString, Element>();
+  final Map<String, Element> importScope =
+      new Map<String, Element>();
 
   /**
    * Adds [element] to the import scope of this library.
@@ -654,58 +672,64 @@
                  Import import,
                  DiagnosticListener listener) {
     LibraryElementX library = enclosingElement.getLibrary();
-    Map<Element, Link<Import>> importers = library.importers;
-    importers[element] =
-        importers.putIfAbsent(element, () => const Link<Import>())
-            .prepend(import);
-    SourceString name = element.name;
-    Element existing = importScope.putIfAbsent(name, () => element);
+    Importers importers = library.importers;
 
-    Element createWarnOnUseElement(Spannable spannable,
-                                   MessageKind messageKind,
-                                   Element hidingElement,
-                                   Element hiddenElement) {
-        Uri hiddenUri = hiddenElement.getLibrary().canonicalUri;
-        Uri hidingUri = hidingElement.getLibrary().canonicalUri;
-        return new WarnOnUseElementX(
-            new WrappedMessage(
-                null, // Report on reference to [hidingElement].
-                messageKind,
-                {'name': name, 'hiddenUri': hiddenUri, 'hidingUri': hidingUri}),
-            new WrappedMessage(
-                listener.spanFromSpannable(spannable),
-                MessageKind.IMPORTED_HERE,
-                {'name': name}),
-            enclosingElement, hidingElement);
+    String name = element.name;
+    Element existing = importScope.putIfAbsent(name, () => element);
+    importers.registerImport(element, import);
+
+    void registerWarnOnUseElement(Import import,
+                                  MessageKind messageKind,
+                                  Element hidingElement,
+                                  Element hiddenElement) {
+      Uri hiddenUri = hiddenElement.getLibrary().canonicalUri;
+      Uri hidingUri = hidingElement.getLibrary().canonicalUri;
+      Element element = new WarnOnUseElementX(
+          new WrappedMessage(
+              null, // Report on reference to [hidingElement].
+              messageKind,
+              {'name': name, 'hiddenUri': hiddenUri, 'hidingUri': hidingUri}),
+          new WrappedMessage(
+              listener.spanFromSpannable(import),
+              MessageKind.IMPORTED_HERE,
+              {'name': name}),
+          enclosingElement, hidingElement);
+      importScope[name] = element;
+      importers.registerImport(element, import);
     }
 
     if (existing != element) {
+      Import existingImport = importers.getImport(existing);
+      Element newElement;
       if (existing.getLibrary().isPlatformLibrary &&
           !element.getLibrary().isPlatformLibrary) {
         // [existing] is implicitly hidden.
-        importScope[name] = createWarnOnUseElement(
+        registerWarnOnUseElement(
             import, MessageKind.HIDDEN_IMPORT, element, existing);
       } else if (!existing.getLibrary().isPlatformLibrary &&
                  element.getLibrary().isPlatformLibrary) {
         // [element] is implicitly hidden.
         if (import == null) {
           // [element] is imported implicitly (probably through dart:core).
-          importScope[name] = createWarnOnUseElement(
-              importers[existing].head, MessageKind.HIDDEN_IMPLICIT_IMPORT,
+          registerWarnOnUseElement(
+              existingImport, MessageKind.HIDDEN_IMPLICIT_IMPORT,
               existing, element);
         } else {
-          importScope[name] = createWarnOnUseElement(
+          registerWarnOnUseElement(
               import, MessageKind.HIDDEN_IMPORT, existing, element);
         }
       } else {
-        importScope[name] = new AmbiguousElementX(
+        Element ambiguousElement = new AmbiguousElementX(
             MessageKind.DUPLICATE_IMPORT, {'name': name},
             enclosingElement, existing, element);
+        importScope[name] = ambiguousElement;
+        importers.registerImport(ambiguousElement, import);
+        importers.registerImport(ambiguousElement, existingImport);
       }
     }
   }
 
-  Element operator [](SourceString name) => importScope[name];
+  Element operator [](String name) => importScope[name];
 }
 
 class LibraryElementX extends ElementX implements LibraryElement {
@@ -735,7 +759,7 @@
   final LibraryElementX origin;
 
   /// A mapping from an imported element to the "import" tag.
-  final Map<Element, Link<Import>> importers;
+  final Importers importers = new Importers();
 
   /**
    * Link for elements exported either through export declarations or through
@@ -752,8 +776,7 @@
 
   LibraryElementX(Script script, [Uri canonicalUri, LibraryElement this.origin])
     : this.canonicalUri = ((canonicalUri == null) ? script.uri : canonicalUri),
-      importers = new Map<Element, Link<Import>>(),
-      super(new SourceString(script.name), ElementKind.LIBRARY, null) {
+      super(script.name, ElementKind.LIBRARY, null) {
     entryCompilationUnit = new CompilationUnitElementX(script, this);
     if (isPatch) {
       origin.patch = this;
@@ -811,7 +834,7 @@
     localScope.add(element, listener);
   }
 
-  Element localLookup(SourceString elementName) {
+  Element localLookup(String elementName) {
     Element result = localScope.lookup(elementName);
     if (result == null && isPatch) {
       result = origin.localLookup(elementName);
@@ -853,7 +876,7 @@
    * null if no such element exist and an [ErroneousElement] if multiple
    * elements have been imported.
    */
-  Element find(SourceString elementName) {
+  Element find(String elementName) {
     Element result = localScope.lookup(elementName);
     if (result != null) return result;
     if (origin != null) {
@@ -871,7 +894,7 @@
 
   /** Look up a top-level element in this library, but only look for
     * non-imported elements. Returns null if no such element exist. */
-  Element findLocal(SourceString elementName) {
+  Element findLocal(String elementName) {
     // TODO(johnniwinther): How to handle injected elements in the patch
     // library?
     Element result = localScope.lookup(elementName);
@@ -904,7 +927,7 @@
     return localScope.values.where((Element element) {
       // At this point [localScope] only contains members so we don't need
       // to check for foreign or prefix elements.
-      return !element.name.isPrivate();
+      return !isPrivateName(element.name);
     });
   }
 
@@ -953,10 +976,10 @@
 
   final ImportScope importScope = new ImportScope();
 
-  PrefixElementX(SourceString prefix, Element enclosing, this.firstPosition)
+  PrefixElementX(String prefix, Element enclosing, this.firstPosition)
       : super(prefix, ElementKind.PREFIX, enclosing);
 
-  Element lookupLocalMember(SourceString memberName) => importScope[memberName];
+  Element lookupLocalMember(String memberName) => importScope[memberName];
 
   DartType computeType(Compiler compiler) => compiler.types.dynamicType;
 
@@ -995,12 +1018,15 @@
    */
   DartType alias;
 
+  /// [:true:] if the typedef has been checked for cyclic reference.
+  bool hasBeenCheckedForCycles = false;
+
   bool get isResolved => mapping != null;
 
   // TODO(johnniwinther): Store the mapping in the resolution enqueuer instead.
   TreeElements mapping;
 
-  TypedefElementX(SourceString name, Element enclosing)
+  TypedefElementX(String name, Element enclosing)
       : super(name, ElementKind.TYPEDEF, enclosing);
 
   /**
@@ -1038,6 +1064,13 @@
   Scope buildScope() {
     return new TypeDeclarationScope(enclosingElement.buildScope(), this);
   }
+
+  void checkCyclicReference(Compiler compiler) {
+    if (hasBeenCheckedForCycles) return;
+    var visitor = new TypedefCyclicVisitor(compiler, this);
+    computeType(compiler).accept(visitor, null);
+    hasBeenCheckedForCycles = true;
+  }
 }
 
 class VariableElementX extends ElementX implements VariableElement {
@@ -1046,7 +1079,7 @@
 
   Modifiers get modifiers => variables.modifiers;
 
-  VariableElementX(SourceString name,
+  VariableElementX(String name,
                    VariableListElement variables,
                    ElementKind kind,
                    this.cachedNode)
@@ -1092,7 +1125,7 @@
     implements FieldParameterElement {
   VariableElement fieldElement;
 
-  FieldParameterElementX(SourceString name,
+  FieldParameterElementX(String name,
                          this.fieldElement,
                          VariableListElement variables,
                          Node node)
@@ -1179,7 +1212,7 @@
   FunctionElement getter;
   FunctionElement setter;
 
-  AbstractFieldElementX(SourceString name, Element enclosing)
+  AbstractFieldElementX(String name, Element enclosing)
       : super(name, ElementKind.ABSTRACT_FIELD, enclosing);
 
   DartType computeType(Compiler compiler) {
@@ -1266,7 +1299,7 @@
     List<Element> list = optionalParameters.toList();
     if (optionalParametersAreNamed) {
       list.sort((Element a, Element b) {
-        return a.name.slowToString().compareTo(b.name.slowToString());
+        return a.name.compareTo(b.name);
       });
     }
     _orderedOptionalParameters = list;
@@ -1304,9 +1337,9 @@
         return false;
       }
       Set<String> names = optionalParameters.toList().map(
-          (Element element) => element.name.slowToString()).toSet();
+          (Element element) => element.name).toSet();
       for (Element namedParameter in signature.optionalParameters) {
-        if (!names.contains(namedParameter.name.slowToString())) {
+        if (!names.contains(namedParameter.name)) {
           return false;
         }
       }
@@ -1347,27 +1380,27 @@
   // TODO(ahe): Rename this field to redirectionTarget.
   FunctionElement defaultImplementation;
 
-  FunctionElementX(SourceString name,
+  FunctionElementX(String name,
                    ElementKind kind,
                    Modifiers modifiers,
                    Element enclosing)
       : this.tooMuchOverloading(name, null, kind, modifiers, enclosing, null);
 
-  FunctionElementX.node(SourceString name,
+  FunctionElementX.node(String name,
                         FunctionExpression node,
                         ElementKind kind,
                         Modifiers modifiers,
                         Element enclosing)
       : this.tooMuchOverloading(name, node, kind, modifiers, enclosing, null);
 
-  FunctionElementX.from(SourceString name,
+  FunctionElementX.from(String name,
                         FunctionElement other,
                         Element enclosing)
       : this.tooMuchOverloading(name, other.cachedNode, other.kind,
                                 other.modifiers, enclosing,
                                 other.functionSignature);
 
-  FunctionElementX.tooMuchOverloading(SourceString name,
+  FunctionElementX.tooMuchOverloading(String name,
                                       FunctionExpression this.cachedNode,
                                       ElementKind kind,
                                       Modifiers this.modifiers,
@@ -1532,7 +1565,7 @@
   final FunctionElement superMember;
   final bool isDefaultConstructor;
 
-  SynthesizedConstructorElementX(SourceString name,
+  SynthesizedConstructorElementX(String name,
                                  this.superMember,
                                  Element enclosing,
                                  this.isDefaultConstructor)
@@ -1542,7 +1575,7 @@
               enclosing);
 
   SynthesizedConstructorElementX.forDefault(superMember, Element enclosing)
-      : this(const SourceString(''), superMember, enclosing, true);
+      : this('', superMember, enclosing, true);
 
   Token position() => enclosingElement.position();
 
@@ -1558,8 +1591,8 @@
           getEnclosingClass().thisType);
     }
     if (superMember.isErroneous()) {
-      return functionSignature = compiler.objectClass.localLookup(
-          const SourceString('')).computeSignature(compiler);
+      return functionSignature = compiler.objectClass.localLookup('')
+          .computeSignature(compiler);
     }
     return functionSignature = superMember.computeSignature(compiler);
   }
@@ -1570,8 +1603,7 @@
 }
 
 class VoidElementX extends ElementX {
-  VoidElementX(Element enclosing)
-      : super(const SourceString('void'), ElementKind.VOID, enclosing);
+  VoidElementX(Element enclosing) : super('void', ElementKind.VOID, enclosing);
   DartType computeType(compiler) => compiler.types.voidType;
   Node parseNode(_) {
     throw 'internal error: parseNode on void';
@@ -1593,7 +1625,7 @@
     var arguments = new LinkBuilder<DartType>();
     for (Link link = parameters.nodes; !link.isEmpty; link = link.tail) {
       TypeVariable node = link.head;
-      SourceString variableName = node.name.source;
+      String variableName = node.name.source;
       TypeVariableElement variableElement =
           new TypeVariableElementX(variableName, element, node);
       TypeVariableType variableType = new TypeVariableType(variableElement);
@@ -1639,7 +1671,7 @@
   InterfaceType rawTypeCache;
   DartType supertype;
   Link<DartType> interfaces;
-  SourceString nativeTagInfo;
+  String nativeTagInfo;
   int supertypeLoadState;
   int resolutionState;
   bool get isResolved => resolutionState == STATE_DONE;
@@ -1650,7 +1682,7 @@
 
   Link<DartType> allSupertypes;
 
-  BaseClassElementX(SourceString name,
+  BaseClassElementX(String name,
                     Element enclosing,
                     this.id,
                     int initialState)
@@ -1730,14 +1762,14 @@
   /**
    * Lookup local members in the class. This will ignore constructors.
    */
-  Element lookupLocalMember(SourceString memberName) {
+  Element lookupLocalMember(String memberName) {
     var result = localLookup(memberName);
     if (result != null && result.isConstructor()) return null;
     return result;
   }
 
   /// Lookup a synthetic element created by the backend.
-  Element lookupBackendMember(SourceString memberName) {
+  Element lookupBackendMember(String memberName) {
     for (Element element in backendMembers) {
       if (element.name == memberName) {
         return element;
@@ -1747,7 +1779,7 @@
   /**
    * Lookup super members for the class. This will ignore constructors.
    */
-  Element lookupSuperMember(SourceString memberName) {
+  Element lookupSuperMember(String memberName) {
     return lookupSuperMemberInLibrary(memberName, getLibrary());
   }
 
@@ -1755,9 +1787,9 @@
    * Lookup super members for the class that is accessible in [library].
    * This will ignore constructors.
    */
-  Element lookupSuperMemberInLibrary(SourceString memberName,
+  Element lookupSuperMemberInLibrary(String memberName,
                                      LibraryElement library) {
-    bool isPrivate = memberName.isPrivate();
+    bool isPrivate = isPrivateName(memberName);
     for (ClassElement s = superclass; s != null; s = s.superclass) {
       // Private members from a different library are not visible.
       if (isPrivate && !identical(library, s.getLibrary())) continue;
@@ -1770,9 +1802,9 @@
     return null;
   }
 
-  Element lookupSuperInterfaceMember(SourceString memberName,
+  Element lookupSuperInterfaceMember(String memberName,
                                      LibraryElement fromLibrary) {
-    bool isPrivate = memberName.isPrivate();
+    bool isPrivate = isPrivateName(memberName);
     for (InterfaceType t in interfaces) {
       ClassElement cls = t.element;
       Element e = cls.lookupLocalMember(memberName);
@@ -1807,8 +1839,8 @@
   Element internalLookupSelector(Selector selector,
                                  Compiler compiler,
                                  bool isSuperLookup) {
-    SourceString name = selector.name;
-    bool isPrivate = name.isPrivate();
+    String name = selector.name;
+    bool isPrivate = isPrivateName(name);
     LibraryElement library = selector.library;
     for (ClassElement current = isSuperLookup ? superclass : this;
          current != null;
@@ -1852,7 +1884,7 @@
    * unqualified sends because it does not implement the scoping
    * rules, where library scope comes before superclass scope.
    */
-  Element lookupMember(SourceString memberName) {
+  Element lookupMember(String memberName) {
     Element localMember = lookupLocalMember(memberName);
     return localMember == null ? lookupSuperMember(memberName) : localMember;
   }
@@ -1865,8 +1897,8 @@
    */
   bool isShadowedByField(Element fieldMember) {
     assert(fieldMember.isField());
-    SourceString fieldName = fieldMember.name;
-    bool isPrivate = fieldName.isPrivate();
+    String fieldName = fieldMember.name;
+    bool isPrivate = isPrivateName(fieldName);
     LibraryElement memberLibrary = fieldMember.getLibrary();
     ClassElement lookupClass = this;
     while (lookupClass != null) {
@@ -1891,7 +1923,7 @@
                                            Element noMatch(Element)) {
     if (result == null
         || !result.isConstructor()
-        || (selector.name.isPrivate()
+        || (isPrivateName(selector.name)
             && result.getLibrary() != selector.library)) {
       result = noMatch != null ? noMatch(result) : null;
     }
@@ -1908,7 +1940,7 @@
 
   Element lookupFactoryConstructor(Selector selector,
                                    [Element noMatch(Element)]) {
-    SourceString constructorName = selector.name;
+    String constructorName = selector.name;
     Element result = localLookup(constructorName);
     return validateConstructorLookupResults(selector, result, noMatch);
   }
@@ -1947,12 +1979,8 @@
                      {includeBackendMembers: false,
                       includeSuperAndInjectedMembers: false}) {
     bool includeInjectedMembers = includeSuperAndInjectedMembers || isPatch;
-    Set<ClassElement> seen = new Set<ClassElement>();
     ClassElement classElement = declaration;
     do {
-      if (seen.contains(classElement)) return;
-      seen.add(classElement);
-
       // Iterate through the members in textual order, which requires
       // to reverse the data structure [localMembers] we created.
       // Textual order may be important for certain operations, for
@@ -1971,7 +1999,7 @@
       classElement = includeSuperAndInjectedMembers
           ? classElement.superclass
           : null;
-    } while(classElement != null);
+    } while (classElement != null);
   }
 
   /**
@@ -2041,7 +2069,7 @@
 
   bool isNative() => nativeTagInfo != null;
   void setNative(String name) {
-    nativeTagInfo = new SourceString(name);
+    nativeTagInfo = name;
   }
 }
 
@@ -2053,7 +2081,7 @@
   Link<Element> localMembers = const Link<Element>();
   final ScopeX localScope = new ScopeX();
 
-  ClassElementX(SourceString name, Element enclosing, int id, int initialState)
+  ClassElementX(String name, Element enclosing, int id, int initialState)
       : super(name, enclosing, id, initialState);
 
   ClassNode parseNode(Compiler compiler);
@@ -2075,7 +2103,7 @@
     localScope.add(element, listener);
   }
 
-  Element localLookup(SourceString elementName) {
+  Element localLookup(String elementName) {
     Element result = localScope.lookup(elementName);
     if (result == null && isPatch) {
       result = origin.localLookup(elementName);
@@ -2129,7 +2157,7 @@
 
   ClassElement mixin;
 
-  MixinApplicationElementX(SourceString name, Element enclosing, int id,
+  MixinApplicationElementX(String name, Element enclosing, int id,
                            this.node, this.modifiers)
       : super(name, enclosing, id, STATE_NOT_STARTED);
 
@@ -2152,7 +2180,7 @@
 
   Node parseNode(DiagnosticListener listener) => node;
 
-  FunctionElement lookupLocalConstructor(SourceString name) {
+  FunctionElement lookupLocalConstructor(String name) {
     for (Link<Element> link = constructors;
          !link.isEmpty;
          link = link.tail) {
@@ -2161,7 +2189,7 @@
     return null;
   }
 
-  Element localLookup(SourceString name) {
+  Element localLookup(String name) {
     Element constructor = lookupLocalConstructor(name);
     if (constructor != null) return constructor;
     if (mixin == null) return null;
@@ -2217,7 +2245,7 @@
         // In case of a synthetic label, just use [labelName] for
         // identifying the element.
         super(label == null
-                  ? new SourceString(labelName)
+                  ? labelName
                   : label.identifier.source,
               ElementKind.LABEL,
               enclosingElement);
@@ -2248,8 +2276,7 @@
   bool isContinueTarget = false;
 
   TargetElementX(this.statement, this.nestingLevel, Element enclosingElement)
-      : super(const SourceString("target"),
-              ElementKind.STATEMENT, enclosingElement);
+      : super("target", ElementKind.STATEMENT, enclosingElement);
   bool get isTarget => isBreakTarget || isContinueTarget;
 
   LabelElement addLabel(Label label, String labelName) {
@@ -2280,7 +2307,7 @@
 
   Node parseNode(compiler) => cachedNode;
 
-  String toString() => "${enclosingElement.toString()}.${name.slowToString()}";
+  String toString() => "${enclosingElement.toString()}.${name}";
 
   Token position() => cachedNode.getBeginToken();
 }
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index c34705ed..c0a5bac 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -20,7 +20,7 @@
 
     void addMemberByName(Element element) {
       element = element.declaration;
-      String name = element.name.slowToString();
+      String name = element.name;
       ScopeContainerElement container = null;
       if (element.isLibrary()) {
         LibraryElement library = element;
@@ -163,7 +163,7 @@
     if (isProcessed(member)) return;
     if (!member.isInstanceMember()) return;
 
-    String memberName = member.name.slowToString();
+    String memberName = member.name;
 
     if (member.kind == ElementKind.FIELD) {
       // The obvious thing to test here would be "member.isNative()",
@@ -283,8 +283,8 @@
   }
 
   void registerNewSelector(Selector selector,
-                           Map<SourceString, Set<Selector>> selectorsMap) {
-    SourceString name = selector.name;
+                           Map<String, Set<Selector>> selectorsMap) {
+    String name = selector.name;
     Set<Selector> selectors =
         selectorsMap.putIfAbsent(name, () => new Set<Selector>());
     if (!selectors.contains(selector)) {
@@ -365,9 +365,8 @@
   }
 
   processLink(Map<String, Link<Element>> map,
-              SourceString n,
+              String memberName,
               bool f(Element e)) {
-    String memberName = n.slowToString();
     Link<Element> members = map[memberName];
     if (members != null) {
       // [f] might add elements to [: map[memberName] :] during the loop below
@@ -382,15 +381,15 @@
     }
   }
 
-  processInstanceMembers(SourceString n, bool f(Element e)) {
+  processInstanceMembers(String n, bool f(Element e)) {
     processLink(instanceMembersByName, n, f);
   }
 
-  processInstanceFunctions(SourceString n, bool f(Element e)) {
+  processInstanceFunctions(String n, bool f(Element e)) {
     processLink(instanceFunctionsByName, n, f);
   }
 
-  void handleUnseenSelector(SourceString methodName, Selector selector) {
+  void handleUnseenSelector(String methodName, Selector selector) {
     processInstanceMembers(methodName, (Element member) {
       if (selector.appliesUnnamed(member, compiler)) {
         if (member.isFunction() && selector.isGetter()) {
@@ -627,8 +626,8 @@
       if (uri == 'dart:isolate') {
         enableIsolateSupport(library);
       } else if (uri == 'dart:async') {
-        if (element.name == const SourceString('_createTimer') ||
-            element.name == const SourceString('_createPeriodicTimer')) {
+        if (element.name == '_createTimer' ||
+            element.name == '_createPeriodicTimer') {
           // The [:Timer:] class uses the event queue of the isolate
           // library, so we make sure that event queue is generated.
           enableIsolateSupport(library);
@@ -659,10 +658,8 @@
         compiler.isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE);
     addToWorkList(startRootIsolate);
     compiler.globalDependencies.registerDependency(startRootIsolate);
-    addToWorkList(compiler.isolateHelperLibrary.find(
-        const SourceString('_currentIsolate')));
-    addToWorkList(compiler.isolateHelperLibrary.find(
-        const SourceString('_callInIsolate')));
+    addToWorkList(compiler.isolateHelperLibrary.find('_currentIsolate'));
+    addToWorkList(compiler.isolateHelperLibrary.find('_callInIsolate'));
   }
 
   void enableNoSuchMethod(Element element) {
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
index 2325cd9..4038a16 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
@@ -133,7 +133,7 @@
 
   // The set of [TypeInformation] where the traced container could
   // flow in, and operations done on them.
-  final Set<TypeInformation> allUsers = new Set<TypeInformation>();
+  final Setlet<TypeInformation> allUsers = new Setlet<TypeInformation>();
 
   // The list of found assignments to the container.
   final List<TypeInformation> assignments = <TypeInformation>[];
@@ -142,7 +142,7 @@
   bool continueAnalyzing = true;
 
   static const int MAX_ANALYSIS_COUNT = 11;
-  final Set<Element> analyzedElements = new Set<Element>();
+  final Setlet<Element> analyzedElements = new Setlet<Element>();
 
   ContainerTracerVisitor(this.container, inferrer)
       : this.inferrer = inferrer, this.compiler = inferrer.compiler;
@@ -220,14 +220,14 @@
   visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
     analyzedElements.add(info.caller);
     Element called = info.calledElement;
-    if (called.isForeign(compiler) && called.name == const SourceString('JS')) {
+    if (called.isForeign(compiler) && called.name == 'JS') {
       bailout('Used in JS ${info.call}');
     }
   }
 
   visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
     Selector selector = info.selector;
-    String selectorName = selector.name.slowToString();
+    String selectorName = selector.name;
     if (allUsers.contains(info.receiver)) {
       if (!okSelectorsSet.contains(selectorName)) {
         if (selector.isCall()) {
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 2a9d49b..801ba63 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -139,8 +139,8 @@
 
   void forEachLocalUntilNode(Node node,
                              void f(Element element, T type),
-                             [Set<Element> seenLocals]) {
-    if (seenLocals == null) seenLocals = new Set<Element>();
+                             [Setlet<Element> seenLocals]) {
+    if (seenLocals == null) seenLocals = new Setlet<Element>();
     if (variables != null) {
       variables.forEach((element, type) {
         if (seenLocals.contains(element)) return;
@@ -221,9 +221,9 @@
  */
 class ArgumentsTypes<T> {
   final List<T> positional;
-  final Map<SourceString, T> named;
+  final Map<String, T> named;
   ArgumentsTypes(this.positional, named)
-    : this.named = (named == null) ? new Map<SourceString, T>() : named;
+    : this.named = (named == null || named.isEmpty) ? const {} : named;
 
   int get length => positional.length + named.length;
 
@@ -757,7 +757,7 @@
       } else {
         Element receiverElement = elements[node.receiver];
         Element argumentElement = elements[node.arguments.first];
-        String operator = node.selector.asOperator().source.stringValue;
+        String operator = node.selector.asOperator().source;
         if ((operator == '==' && usePositive)
             || (operator == '!=' && !usePositive)) {
           // Type the elements as null.
@@ -783,9 +783,9 @@
 
   T visitOperatorSend(Send node) {
     Operator op = node.selector;
-    if (const SourceString("[]") == op.source) {
+    if ("[]" == op.source) {
       return visitDynamicSend(node);
-    } else if (const SourceString("&&") == op.source) {
+    } else if ("&&" == op.source) {
       conditionIsSimple = false;
       bool oldAccumulateIsChecks = accumulateIsChecks;
       accumulateIsChecks = true;
@@ -800,7 +800,7 @@
       saved.mergeDiamondFlow(locals, null);
       locals = saved;
       return types.boolType;
-    } else if (const SourceString("||") == op.source) {
+    } else if ("||" == op.source) {
       conditionIsSimple = false;
       List<Send> tests = <Send>[];
       handleCondition(node.receiver, tests);
@@ -814,25 +814,25 @@
       saved.mergeDiamondFlow(locals, null);
       locals = saved;
       return types.boolType;
-    } else if (const SourceString("!") == op.source) {
+    } else if ("!" == op.source) {
       bool oldAccumulateIsChecks = accumulateIsChecks;
       accumulateIsChecks = false;
       node.visitChildren(this);
       accumulateIsChecks = oldAccumulateIsChecks;
       return types.boolType;
-    } else if (const SourceString("is") == op.source) {
+    } else if ("is" == op.source) {
       potentiallyAddIsCheck(node);
       node.visitChildren(this);
       return types.boolType;
-    } else if (const SourceString("as") == op.source) {
+    } else if ("as" == op.source) {
       T receiverType = visit(node.receiver);
       DartType type = elements.getType(node.arguments.head);
       return types.narrowType(receiverType, type);
     } else if (node.argumentsNode is Prefix) {
       // Unary operator.
       return visitDynamicSend(node);
-    } else if (const SourceString('===') == op.source
-               || const SourceString('!==') == op.source) {
+    } else if ('===' == op.source
+               || '!==' == op.source) {
       node.visitChildren(this);
       return types.boolType;
     } else {
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 932eb33..8db325d 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -10,7 +10,7 @@
 import '../elements/elements.dart';
 import '../native_handler.dart' as native;
 import '../tree/tree.dart';
-import '../util/util.dart' show Link, Spannable;
+import '../util/util.dart' show Link, Spannable, Setlet;
 import '../types/types.dart'
     show TypesInferrer, FlatTypeMask, TypeMask, ContainerTypeMask,
          ElementTypeMask, TypeSystem, MinimalInferrerEngine;
@@ -33,7 +33,6 @@
                       DartType annotation,
                       {bool isNullable: true}) {
     if (annotation.treatAsDynamic) return type;
-    if (annotation.isVoid) return nullType;
     if (annotation.element == compiler.objectClass) return type;
     TypeMask otherType;
     if (annotation.kind == TypeKind.TYPEDEF
@@ -42,6 +41,8 @@
     } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
       // TODO(ngeoffray): Narrow to bound.
       return type;
+    } else if (annotation.isVoid) {
+      otherType = nullType;
     } else {
       assert(annotation.kind == TypeKind.INTERFACE);
       otherType = new TypeMask.nonNullSubtype(annotation.element);
@@ -379,7 +380,7 @@
   SideEffects sideEffects = new SideEffects.empty();
   final Element outermostElement;
   final InferrerEngine<T, TypeSystem<T>> inferrer;
-  final Set<Element> capturedVariables = new Set<Element>();
+  final Setlet<Element> capturedVariables = new Setlet<Element>();
 
   SimpleTypeInferrerVisitor.internal(analyzedElement,
                                      this.outermostElement,
@@ -618,7 +619,7 @@
         elements.getOperatorSelectorInComplexSendSet(node);
     Selector setterSelector = elements.getSelector(node);
 
-    String op = node.assignmentOperator.source.stringValue;
+    String op = node.assignmentOperator.source;
     bool isIncrementOrDecrement = op == '++' || op == '--';
 
     T receiverType;
@@ -858,17 +859,17 @@
   T handleForeignSend(Send node) {
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
-    SourceString name = selector.name;
+    String name = selector.name;
     handleStaticSend(node, selector, elements[node], arguments);
-    if (name == const SourceString('JS')) {
+    if (name == 'JS') {
       native.NativeBehavior nativeBehavior =
           compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
       sideEffects.add(nativeBehavior.sideEffects);
       return inferrer.typeOfNativeBehavior(nativeBehavior);
-    } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')
-               || name == const SourceString('JS_OPERATOR_AS_PREFIX')
-               || name == const SourceString('JS_OBJECT_CLASS_NAME')
-               || name == const SourceString('JS_NULL_CLASS_NAME')) {
+    } else if (name == 'JS_OPERATOR_IS_PREFIX'
+               || name == 'JS_OPERATOR_AS_PREFIX'
+               || name == 'JS_OBJECT_CLASS_NAME'
+               || name == 'JS_NULL_CLASS_NAME') {
       return types.stringType;
     } else {
       sideEffects.setAllSideEffects();
@@ -878,11 +879,12 @@
 
   ArgumentsTypes analyzeArguments(Link<Node> arguments) {
     List<T> positional = [];
-    Map<SourceString, T> named = new Map<SourceString, T>();
+    Map<String, T> named;
     for (var argument in arguments) {
       NamedArgument namedArgument = argument.asNamedArgument();
       if (namedArgument != null) {
         argument = namedArgument.expression;
+        if (named == null) named = new Map<String, T>();
         named[namedArgument.name.source] = argument.accept(this);
       } else {
         positional.add(argument.accept(this));
@@ -999,8 +1001,8 @@
     ArgumentsTypes arguments = node.isPropertyAccess
         ? null
         : analyzeArguments(node.arguments);
-    if (selector.name == const SourceString('==')
-        || selector.name == const SourceString('!=')) {
+    if (selector.name == '=='
+        || selector.name == '!=') {
       if (types.isNull(receiverType)) {
         potentiallyAddNullCheck(node, node.arguments.head);
         return types.boolType;
@@ -1026,18 +1028,23 @@
     }
 
     List<T> unnamed = <T>[];
-    Map<SourceString, T> named = new Map<SourceString, T>();
     signature.forEachRequiredParameter((Element element) {
       assert(locals.use(element) != null);
       unnamed.add(locals.use(element));
     });
-    signature.forEachOptionalParameter((Element element) {
-      if (signature.optionalParametersAreNamed) {
+
+    Map<String, T> named;
+    if (signature.optionalParametersAreNamed) {
+      named = new Map<String, T>();
+      signature.forEachOptionalParameter((Element element) {
         named[element.name] = locals.use(element);
-      } else {
+      });
+    } else {
+      signature.forEachOptionalParameter((Element element) {
         unnamed.add(locals.use(element));
-      }
-    });
+      });
+    }
+
     ArgumentsTypes arguments = new ArgumentsTypes<T>(unnamed, named);
     return inferrer.registerCalledElement(node,
                                           null,
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 3c2a39c..a9e1734 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -10,10 +10,10 @@
 import '../tree/tree.dart' show LiteralList, Node;
 import '../types/types.dart' show TypeMask, ContainerTypeMask, TypesInferrer;
 import '../universe/universe.dart' show Selector, TypedSelector, SideEffects;
-import '../dart2jslib.dart' show Compiler, SourceString, TreeElementMapping;
+import '../dart2jslib.dart' show Compiler, TreeElementMapping;
 import 'inferrer_visitor.dart' show TypeSystem, ArgumentsTypes;
 import '../native_handler.dart' as native;
-import '../util/util.dart' show Spannable;
+import '../util/util.dart' show Spannable, Setlet;
 import 'simple_types_inferrer.dart';
 import '../dart2jslib.dart' show invariant;
 
@@ -26,14 +26,14 @@
  */
 Set<Selector> returnsElementTypeSet = new Set<Selector>.from(
   <Selector>[
-    new Selector.getter(const SourceString('first'), null),
-    new Selector.getter(const SourceString('last'), null),
-    new Selector.getter(const SourceString('single'), null),
-    new Selector.call(const SourceString('singleWhere'), null, 1),
-    new Selector.call(const SourceString('elementAt'), null, 1),
+    new Selector.getter('first', null),
+    new Selector.getter('last', null),
+    new Selector.getter('single', null),
+    new Selector.call('singleWhere', null, 1),
+    new Selector.call('elementAt', null, 1),
     new Selector.index(),
-    new Selector.call(const SourceString('removeAt'), null, 1),
-    new Selector.call(const SourceString('removeLast'), null, 0)
+    new Selector.call('removeAt', null, 1),
+    new Selector.call('removeLast', null, 0)
   ]);
 
 bool returnsElementType(Selector selector) {
@@ -643,7 +643,7 @@
 
   void recordReturnType(Element element, TypeInformation type) {
     TypeInformation info = types.getInferredTypeOf(element);
-    if (element.name == const SourceString('==')) {
+    if (element.name == '==') {
       info.addAssignment(types.boolType);
     }
     // TODO(ngeoffray): Clean up. We do these checks because
@@ -723,7 +723,7 @@
   // [SimpleTypesInferrer].
   Iterable<Element> sortResolvedElements() {
     int max = 0;
-    Map<int, Set<Element>> methodSizes = new Map<int, Set<Element>>();
+    Map<int, Setlet<Element>> methodSizes = new Map<int, Setlet<Element>>();
     compiler.enqueuer.resolution.resolvedElements.forEach(
       (Element element, TreeElementMapping mapping) {
         element = element.implementation;
@@ -743,18 +743,15 @@
         // length order.
         int length = mapping.selectors.length;
         max = length > max ? length : max;
-        Set<Element> set = methodSizes.putIfAbsent(
-            length, () => new Set<Element>());
+        Setlet<Element> set = methodSizes.putIfAbsent(
+            length, () => new Setlet<Element>());
         set.add(element);
     });
 
     List<Element> result = <Element>[];
-
     for (int i = 0; i <= max; i++) {
-      Set<Element> set = methodSizes[i];
-      if (set != null) {
-        result.addAll(set);
-      }
+      Setlet<Element> set = methodSizes[i];
+      if (set != null) result.addAll(set);
     }
     return result;
   }
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 1d09322..9c32288 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -46,7 +46,7 @@
   bool get isConcrete => false;
 
   TypeInformation([users, assignments])
-      : users = (users == null) ? new Set<TypeInformation>() : users,
+      : users = (users == null) ? new Setlet<TypeInformation>() : users,
         assignments = (assignments == null) ? <TypeInformation>[] : assignments;
 
 
@@ -176,8 +176,8 @@
  */
 class ElementTypeInformation extends TypeInformation {
   final Element element;
-  final Map<Element, Set<Spannable>> callers =
-      new Map<Element, Set<Spannable>>();
+  final Map<Element, Setlet<Spannable>> callers =
+      new Map<Element, Setlet<Spannable>>();
 
   ElementTypeInformation.internal(this.element, assignments)
       : super(null, assignments);
@@ -192,11 +192,11 @@
   }
 
   void addCall(Element caller, Spannable node) {
-    callers.putIfAbsent(caller, () => new Set<Spannable>()).add(node);
+    callers.putIfAbsent(caller, () => new Setlet<Spannable>()).add(node);
   }
 
   void removeCall(Element caller, Spannable node) {
-    Set<Spannable> calls = callers[caller];
+    Setlet<Spannable> calls = callers[caller];
     if (calls == null) return;
     calls.remove(node);
     if (calls.isEmpty) {
@@ -442,11 +442,8 @@
     if (!arguments.named.isEmpty) return null;
     if (arguments.positional.length > 1) return null;
 
-    SourceString name = selector.name;
-    if (name == const SourceString('*')
-        || name == const SourceString('+')
-        || name == const SourceString('%')
-        || name == const SourceString('remainder')) {
+    String name = selector.name;
+    if (name == '*' || name == '+' || name == '%' || name == 'remainder') {
       if (hasOnePositionalArgumentWithType(intType)) {
         return inferrer.types.intType;
       } else if (hasOnePositionalArgumentWithType(emptyType)) {
@@ -454,7 +451,7 @@
       } else {
         return null;
       }
-    } else if (name == const SourceString('-')) {
+    } else if (name == '-') {
       if (arguments.hasNoArguments()) return inferrer.types.intType;
       if (hasOnePositionalArgumentWithType(intType)) {
         return inferrer.types.intType;
@@ -462,7 +459,7 @@
         return inferrer.types.nonNullEmptyType;
       }
       return null;
-    } else if (name == const SourceString('abs')) {
+    } else if (name == 'abs') {
       return arguments.hasNoArguments() ? inferrer.types.intType : null;
     }
     return null;
diff --git a/sdk/lib/_internal/compiler/implementation/js/nodes.dart b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
index 04eafb9..c102b39 100644
--- a/sdk/lib/_internal/compiler/implementation/js/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
@@ -821,7 +821,7 @@
 
   PropertyAccess(this.receiver, this.selector);
   PropertyAccess.field(this.receiver, String fieldName)
-      : selector = new LiteralString("'$fieldName'");
+      : selector = new LiteralString('"$fieldName"');
   PropertyAccess.indexed(this.receiver, int index)
       : selector = new LiteralNumber('$index');
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 4922a78..de44eee 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -12,9 +12,9 @@
 }
 
 class CheckedModeHelper {
-  final SourceString name;
+  final String name;
 
-  const CheckedModeHelper(SourceString this.name);
+  const CheckedModeHelper(String this.name);
 
   Element getElement(Compiler compiler) => compiler.findHelper(name);
 
@@ -38,7 +38,7 @@
 }
 
 class PropertyCheckedModeHelper extends CheckedModeHelper {
-  const PropertyCheckedModeHelper(SourceString name) : super(name);
+  const PropertyCheckedModeHelper(String name) : super(name);
 
   void generateAdditionalArguments(SsaCodeGenerator codegen,
                                    HTypeConversion node,
@@ -50,7 +50,7 @@
 }
 
 class TypeVariableCheckedModeHelper extends CheckedModeHelper {
-  const TypeVariableCheckedModeHelper(SourceString name) : super(name);
+  const TypeVariableCheckedModeHelper(String name) : super(name);
 
   void generateAdditionalArguments(SsaCodeGenerator codegen,
                                    HTypeConversion node,
@@ -62,7 +62,7 @@
 }
 
 class SubtypeCheckedModeHelper extends CheckedModeHelper {
-  const SubtypeCheckedModeHelper(SourceString name) : super(name);
+  const SubtypeCheckedModeHelper(String name) : super(name);
 
   void generateAdditionalArguments(SsaCodeGenerator codegen,
                                    HTypeConversion node,
@@ -79,7 +79,7 @@
 }
 
 class FunctionTypeCheckedModeHelper extends CheckedModeHelper {
-  const FunctionTypeCheckedModeHelper(SourceString name) : super(name);
+  const FunctionTypeCheckedModeHelper(String name) : super(name);
 
   void generateAdditionalArguments(SsaCodeGenerator codegen,
                                    HTypeConversion node,
@@ -200,6 +200,7 @@
   ClassElement typeLiteralClass;
   ClassElement mapLiteralClass;
   ClassElement constMapLiteralClass;
+  ClassElement typeVariableClass;
 
   Element getInterceptorMethod;
   Element interceptedNames;
@@ -223,7 +224,6 @@
   // classes.
   Element dispatchPropertyName;
   Element getNativeInterceptorMethod;
-  Element defineNativeMethodsFinishMethod;
   bool needToInitializeDispatchProperty = false;
 
   bool seenAnyClass = false;
@@ -248,7 +248,7 @@
    * list of members that have that name. This map is used by the codegen to
    * know whether a send must be intercepted or not.
    */
-  final Map<SourceString, Set<Element>> interceptedElements;
+  final Map<String, Set<Element>> interceptedElements;
   // TODO(sra): Not all methods in the Set always require an interceptor.  A
   // method may be mixed into a true interceptor *and* a plain class. For the
   // method to work on the interceptor class it needs to use the explicit
@@ -342,69 +342,49 @@
 
   /// All the checked mode helpers.
   static const checkedModeHelpers = const [
-      const CheckedModeHelper(const SourceString('voidTypeCheck')),
-      const CheckedModeHelper(const SourceString('stringTypeCast')),
-      const CheckedModeHelper(const SourceString('stringTypeCheck')),
-      const CheckedModeHelper(const SourceString('doubleTypeCast')),
-      const CheckedModeHelper(const SourceString('doubleTypeCheck')),
-      const CheckedModeHelper(const SourceString('numTypeCast')),
-      const CheckedModeHelper(const SourceString('numTypeCheck')),
-      const CheckedModeHelper(const SourceString('boolTypeCast')),
-      const CheckedModeHelper(const SourceString('boolTypeCheck')),
-      const CheckedModeHelper(const SourceString('intTypeCast')),
-      const CheckedModeHelper(const SourceString('intTypeCheck')),
-      const PropertyCheckedModeHelper(
-          const SourceString('numberOrStringSuperNativeTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('numberOrStringSuperNativeTypeCheck')),
-      const PropertyCheckedModeHelper(
-          const SourceString('numberOrStringSuperTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('numberOrStringSuperTypeCheck')),
-      const PropertyCheckedModeHelper(
-          const SourceString('stringSuperNativeTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('stringSuperNativeTypeCheck')),
-      const PropertyCheckedModeHelper(
-          const SourceString('stringSuperTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('stringSuperTypeCheck')),
-      const CheckedModeHelper(const SourceString('listTypeCast')),
-      const CheckedModeHelper(const SourceString('listTypeCheck')),
-      const PropertyCheckedModeHelper(
-          const SourceString('listSuperNativeTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('listSuperNativeTypeCheck')),
-      const PropertyCheckedModeHelper(
-          const SourceString('listSuperTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('listSuperTypeCheck')),
-      const PropertyCheckedModeHelper(
-          const SourceString('interceptedTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('interceptedTypeCheck')),
-      const SubtypeCheckedModeHelper(
-          const SourceString('subtypeCast')),
-      const SubtypeCheckedModeHelper(
-          const SourceString('assertSubtype')),
-      const TypeVariableCheckedModeHelper(
-          const SourceString('subtypeOfRuntimeTypeCast')),
-      const TypeVariableCheckedModeHelper(
-          const SourceString('assertSubtypeOfRuntimeType')),
-      const FunctionTypeCheckedModeHelper(
-          const SourceString('functionSubtypeCast')),
-      const FunctionTypeCheckedModeHelper(
-          const SourceString('assertFunctionSubtype')),
-      const PropertyCheckedModeHelper(
-          const SourceString('propertyTypeCast')),
-      const PropertyCheckedModeHelper(
-          const SourceString('propertyTypeCheck')) ];
+      const CheckedModeHelper('voidTypeCheck'),
+      const CheckedModeHelper('stringTypeCast'),
+      const CheckedModeHelper('stringTypeCheck'),
+      const CheckedModeHelper('doubleTypeCast'),
+      const CheckedModeHelper('doubleTypeCheck'),
+      const CheckedModeHelper('numTypeCast'),
+      const CheckedModeHelper('numTypeCheck'),
+      const CheckedModeHelper('boolTypeCast'),
+      const CheckedModeHelper('boolTypeCheck'),
+      const CheckedModeHelper('intTypeCast'),
+      const CheckedModeHelper('intTypeCheck'),
+      const PropertyCheckedModeHelper('numberOrStringSuperNativeTypeCast'),
+      const PropertyCheckedModeHelper('numberOrStringSuperNativeTypeCheck'),
+      const PropertyCheckedModeHelper('numberOrStringSuperTypeCast'),
+      const PropertyCheckedModeHelper('numberOrStringSuperTypeCheck'),
+      const PropertyCheckedModeHelper('stringSuperNativeTypeCast'),
+      const PropertyCheckedModeHelper('stringSuperNativeTypeCheck'),
+      const PropertyCheckedModeHelper('stringSuperTypeCast'),
+      const PropertyCheckedModeHelper('stringSuperTypeCheck'),
+      const CheckedModeHelper('listTypeCast'),
+      const CheckedModeHelper('listTypeCheck'),
+      const PropertyCheckedModeHelper('listSuperNativeTypeCast'),
+      const PropertyCheckedModeHelper('listSuperNativeTypeCheck'),
+      const PropertyCheckedModeHelper('listSuperTypeCast'),
+      const PropertyCheckedModeHelper('listSuperTypeCheck'),
+      const PropertyCheckedModeHelper('interceptedTypeCast'),
+      const PropertyCheckedModeHelper('interceptedTypeCheck'),
+      const SubtypeCheckedModeHelper('subtypeCast'),
+      const SubtypeCheckedModeHelper('assertSubtype'),
+      const TypeVariableCheckedModeHelper('subtypeOfRuntimeTypeCast'),
+      const TypeVariableCheckedModeHelper('assertSubtypeOfRuntimeType'),
+      const FunctionTypeCheckedModeHelper('functionSubtypeCast'),
+      const FunctionTypeCheckedModeHelper('assertFunctionSubtype'),
+      const PropertyCheckedModeHelper('propertyTypeCast'),
+      const PropertyCheckedModeHelper('propertyTypeCheck') ];
 
   // Checked mode helpers indexed by name.
   Map<String, CheckedModeHelper> checkedModeHelperByName =
       new Map<String, CheckedModeHelper>.fromIterable(
           checkedModeHelpers,
-          key: (helper) => helper.name.slowToString());
+          key: (helper) => helper.name);
+
+  TypeVariableHandler typeVariableHandler;
 
   /// Number of methods compiled before considering reflection.
   int preMirrorsMethodCount = 0;
@@ -416,7 +396,7 @@
   JavaScriptBackend(Compiler compiler, bool generateSourceMap)
       : namer = determineNamer(compiler),
         oneShotInterceptors = new Map<String, Selector>(),
-        interceptedElements = new Map<SourceString, Set<Element>>(),
+        interceptedElements = new Map<String, Set<Element>>(),
         rti = new RuntimeTypes(compiler),
         specializedGetInterceptors = new Map<String, Set<ClassElement>>(),
         super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
@@ -424,6 +404,7 @@
     builder = new SsaBuilderTask(this);
     optimizer = new SsaOptimizerTask(this);
     generator = new SsaCodeGeneratorTask(this);
+    typeVariableHandler = new TypeVariableHandler(this);
     customElementsAnalysis = new CustomElementsAnalysis(this);
   }
 
@@ -499,7 +480,7 @@
     return interceptedElements[element.name] != null;
   }
 
-  bool isInterceptedName(SourceString name) {
+  bool isInterceptedName(String name) {
     return interceptedElements[name] != null;
   }
 
@@ -507,14 +488,14 @@
     return interceptedElements[selector.name] != null;
   }
 
-  final Map<SourceString, Set<ClassElement>> interceptedClassesCache =
-      new Map<SourceString, Set<ClassElement>>();
+  final Map<String, Set<ClassElement>> interceptedClassesCache =
+      new Map<String, Set<ClassElement>>();
 
   /**
    * Returns a set of interceptor classes that contain a member named
    * [name]. Returns [:null:] if there is no class.
    */
-  Set<ClassElement> getInterceptedClassesOn(SourceString name) {
+  Set<ClassElement> getInterceptedClassesOn(String name) {
     Set<Element> intercepted = interceptedElements[name];
     if (intercepted == null) return null;
     return interceptedClassesCache.putIfAbsent(name, () {
@@ -561,51 +542,39 @@
   }
 
   void initializeHelperClasses() {
-    getInterceptorMethod =
-        compiler.findInterceptor(const SourceString('getInterceptor'));
-    interceptedNames =
-        compiler.findInterceptor(const SourceString('interceptedNames'));
-    mapTypeToInterceptor =
-        compiler.findInterceptor(const SourceString('mapTypeToInterceptor'));
-    dispatchPropertyName =
-        compiler.findInterceptor(const SourceString('dispatchPropertyName'));
+    getInterceptorMethod = compiler.findInterceptor('getInterceptor');
+    interceptedNames = compiler.findInterceptor('interceptedNames');
+    mapTypeToInterceptor = compiler.findInterceptor('mapTypeToInterceptor');
+    dispatchPropertyName = compiler.findInterceptor('dispatchPropertyName');
     getNativeInterceptorMethod =
-        compiler.findInterceptor(const SourceString('getNativeInterceptor'));
-    defineNativeMethodsFinishMethod =
-        compiler.findHelper(const SourceString('defineNativeMethodsFinish'));
+        compiler.findInterceptor('getNativeInterceptor');
 
     // These methods are overwritten with generated versions.
     inlineCache.markAsNonInlinable(getInterceptorMethod, insideLoop: true);
 
     List<ClassElement> classes = [
       jsInterceptorClass =
-          compiler.findInterceptor(const SourceString('Interceptor')),
-      jsStringClass = compiler.findInterceptor(const SourceString('JSString')),
-      jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')),
+          compiler.findInterceptor('Interceptor'),
+      jsStringClass = compiler.findInterceptor('JSString'),
+      jsArrayClass = compiler.findInterceptor('JSArray'),
       // The int class must be before the double class, because the
       // emitter relies on this list for the order of type checks.
-      jsIntClass = compiler.findInterceptor(const SourceString('JSInt')),
-      jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')),
-      jsNumberClass = compiler.findInterceptor(const SourceString('JSNumber')),
-      jsNullClass = compiler.findInterceptor(const SourceString('JSNull')),
-      jsBoolClass = compiler.findInterceptor(const SourceString('JSBool')),
-      jsMutableArrayClass =
-          compiler.findInterceptor(const SourceString('JSMutableArray')),
-      jsFixedArrayClass =
-          compiler.findInterceptor(const SourceString('JSFixedArray')),
-      jsExtendableArrayClass =
-          compiler.findInterceptor(const SourceString('JSExtendableArray')),
+      jsIntClass = compiler.findInterceptor('JSInt'),
+      jsDoubleClass = compiler.findInterceptor('JSDouble'),
+      jsNumberClass = compiler.findInterceptor('JSNumber'),
+      jsNullClass = compiler.findInterceptor('JSNull'),
+      jsBoolClass = compiler.findInterceptor('JSBool'),
+      jsMutableArrayClass = compiler.findInterceptor('JSMutableArray'),
+      jsFixedArrayClass = compiler.findInterceptor('JSFixedArray'),
+      jsExtendableArrayClass = compiler.findInterceptor('JSExtendableArray'),
       jsPlainJavaScriptObjectClass =
-          compiler.findInterceptor(const SourceString('PlainJavaScriptObject')),
+          compiler.findInterceptor('PlainJavaScriptObject'),
       jsUnknownJavaScriptObjectClass =
-          compiler.findInterceptor(
-              const SourceString('UnknownJavaScriptObject')),
+          compiler.findInterceptor('UnknownJavaScriptObject'),
     ];
 
-    jsIndexableClass =
-        compiler.findInterceptor(const SourceString('JSIndexable'));
-    jsMutableIndexableClass =
-        compiler.findInterceptor(const SourceString('JSMutableIndexable'));
+    jsIndexableClass = compiler.findInterceptor('JSIndexable');
+    jsMutableIndexableClass = compiler.findInterceptor('JSMutableIndexable');
 
     // TODO(kasperl): Some tests do not define the special JSArray
     // subclasses, so we check to see if they are defined before
@@ -619,37 +588,29 @@
 
     jsIndexableClass.ensureResolved(compiler);
     jsIndexableLength = compiler.lookupElementIn(
-        jsIndexableClass, const SourceString('length'));
+        jsIndexableClass, 'length');
     if (jsIndexableLength != null && jsIndexableLength.isAbstractField()) {
       AbstractFieldElement element = jsIndexableLength;
       jsIndexableLength = element.getter;
     }
 
     jsArrayClass.ensureResolved(compiler);
-    jsArrayRemoveLast = compiler.lookupElementIn(
-        jsArrayClass, const SourceString('removeLast'));
-    jsArrayAdd = compiler.lookupElementIn(
-        jsArrayClass, const SourceString('add'));
+    jsArrayRemoveLast = compiler.lookupElementIn(jsArrayClass, 'removeLast');
+    jsArrayAdd = compiler.lookupElementIn(jsArrayClass, 'add');
 
     jsStringClass.ensureResolved(compiler);
-    jsStringSplit = compiler.lookupElementIn(
-        jsStringClass, const SourceString('split'));
-    jsStringOperatorAdd = compiler.lookupElementIn(
-        jsStringClass, const SourceString('+'));
-    jsStringToString = compiler.lookupElementIn(
-        jsStringClass, const SourceString('toString'));
+    jsStringSplit = compiler.lookupElementIn(jsStringClass, 'split');
+    jsStringOperatorAdd = compiler.lookupElementIn(jsStringClass, '+');
+    jsStringToString = compiler.lookupElementIn(jsStringClass, 'toString');
 
-    typeLiteralClass = compiler.findHelper(const SourceString('TypeImpl'));
-    mapLiteralClass =
-        compiler.coreLibrary.find(const SourceString('LinkedHashMap'));
-    constMapLiteralClass =
-        compiler.findHelper(const SourceString('ConstantMap'));
+    typeLiteralClass = compiler.findHelper('TypeImpl');
+    mapLiteralClass = compiler.coreLibrary.find('LinkedHashMap');
+    constMapLiteralClass = compiler.findHelper('ConstantMap');
 
-    objectEquals = compiler.lookupElementIn(
-        compiler.objectClass, const SourceString('=='));
+    objectEquals = compiler.lookupElementIn(compiler.objectClass, '==');
 
     jsIndexingBehaviorInterface =
-        compiler.findHelper(const SourceString('JavaScriptIndexingBehavior'));
+        compiler.findHelper('JavaScriptIndexingBehavior');
 
     specialOperatorEqClasses
         ..add(compiler.objectClass)
@@ -670,6 +631,9 @@
         new TypeMask.nonNullExact(jsFixedArrayClass));
     extendableArrayType = new HBoundedType(
         new TypeMask.nonNullExact(jsExtendableArrayClass));
+
+    typeVariableClass =
+        compiler.findHelper('TypeVariable');
   }
 
   void validateInterceptorImplementsAllObjectMethods(
@@ -797,13 +761,16 @@
   void registerInstantiatedClass(ClassElement cls,
                                  Enqueuer enqueuer,
                                  TreeElements elements) {
+    if (!cls.typeVariables.isEmpty) {
+      typeVariableHandler.registerClassWithTypeVariables(cls);
+    }
+
     if (!seenAnyClass) {
       seenAnyClass = true;
       if (enqueuer.isResolutionQueue) {
         // TODO(9577): Make it so that these are not needed when there are no
         // native classes.
         enqueue(enqueuer, getNativeInterceptorMethod, elements);
-        enqueue(enqueuer, defineNativeMethodsFinishMethod, elements);
         enqueueClass(enqueuer, jsInterceptorClass, compiler.globalDependencies);
       }
     }
@@ -816,17 +783,17 @@
         // The backend will try to optimize number operations and use the
         // `iae` helper directly.
         enqueue(enqueuer,
-                compiler.findHelper(const SourceString('iae')),
+                compiler.findHelper('iae'),
                 elements);
       } else if (cls == compiler.listClass
                  || cls == compiler.stringClass) {
         // The backend will try to optimize array and string access and use the
         // `ioore` and `iae` helpers directly.
         enqueue(enqueuer,
-                compiler.findHelper(const SourceString('ioore')),
+                compiler.findHelper('ioore'),
                 elements);
         enqueue(enqueuer,
-                compiler.findHelper(const SourceString('iae')),
+                compiler.findHelper('iae'),
                 elements);
       } else if (cls == compiler.functionClass) {
         enqueueClass(enqueuer, compiler.closureClass, elements);
@@ -879,11 +846,11 @@
       // we make sure they are always generated.
       enqueue(
           enqueuer,
-          compiler.findHelper(const SourceString('isJsIndexable')),
+          compiler.findHelper('isJsIndexable'),
           elements);
       enqueue(
           enqueuer,
-          compiler.findInterceptor(const SourceString('dispatchPropertyName')),
+          compiler.findInterceptor('dispatchPropertyName'),
           elements);
     }
 
@@ -895,7 +862,6 @@
     if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return;
     TreeElements elements = compiler.globalDependencies;
     enqueue(enqueuer, getNativeInterceptorMethod, elements);
-    enqueue(enqueuer, defineNativeMethodsFinishMethod, elements);
     enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, elements);
     needToInitializeDispatchProperty = true;
   }
@@ -915,7 +881,7 @@
       // expression in an if/while/for is a boolean.
       // TODO(ngeoffray): Should we have the resolver register those instead?
       Element e =
-          compiler.findHelper(const SourceString('boolConversionCheck'));
+          compiler.findHelper('boolConversionCheck');
       if (e != null) enqueue(world, e, elements);
     }
     registerCheckedModeHelpers(elements);
@@ -1066,7 +1032,7 @@
       // JavaScript object prototype, so we make sure
       // [:defineProperty:] is compiled.
       enqueue(world,
-              compiler.findHelper(const SourceString('defineProperty')),
+              compiler.findHelper('defineProperty'),
               elements);
     }
   }
@@ -1173,7 +1139,7 @@
   }
 
   bool isDefaultEqualityImplementation(Element element) {
-    assert(element.name == const SourceString('=='));
+    assert(element.name == '==');
     ClassElement classElement = element.getEnclosingClass();
     return classElement == compiler.objectClass
         || classElement == jsInterceptorClass
@@ -1217,7 +1183,7 @@
   }
 
   void registerConstantMap(TreeElements elements) {
-    void enqueue(SourceString name) {
+    void enqueue(String name) {
       Element e = compiler.findHelper(name);
       if (e != null) {
         enqueueClass(compiler.enqueuer.resolution, e, elements);
@@ -1506,97 +1472,95 @@
   }
 
   Element getExceptionUnwrapper() {
-    return compiler.findHelper(const SourceString('unwrapException'));
+    return compiler.findHelper('unwrapException');
   }
 
   Element getThrowRuntimeError() {
-    return compiler.findHelper(const SourceString('throwRuntimeError'));
+    return compiler.findHelper('throwRuntimeError');
   }
 
   Element getThrowAbstractClassInstantiationError() {
-    return compiler.findHelper(
-        const SourceString('throwAbstractClassInstantiationError'));
+    return compiler.findHelper('throwAbstractClassInstantiationError');
   }
 
   Element getStringInterpolationHelper() {
-    return compiler.findHelper(const SourceString('S'));
+    return compiler.findHelper('S');
   }
 
   Element getWrapExceptionHelper() {
-    return compiler.findHelper(const SourceString(r'wrapException'));
+    return compiler.findHelper(r'wrapException');
   }
 
   Element getThrowExpressionHelper() {
-    return compiler.findHelper(const SourceString('throwExpression'));
+    return compiler.findHelper('throwExpression');
   }
 
   Element getClosureConverter() {
-    return compiler.findHelper(const SourceString('convertDartClosureToJS'));
+    return compiler.findHelper('convertDartClosureToJS');
   }
 
   Element getTraceFromException() {
-    return compiler.findHelper(const SourceString('getTraceFromException'));
+    return compiler.findHelper('getTraceFromException');
   }
 
   Element getMapMaker() {
-    return compiler.findHelper(const SourceString('makeLiteralMap'));
+    return compiler.findHelper('makeLiteralMap');
   }
 
   Element getSetRuntimeTypeInfo() {
-    return compiler.findHelper(const SourceString('setRuntimeTypeInfo'));
+    return compiler.findHelper('setRuntimeTypeInfo');
   }
 
   Element getGetRuntimeTypeInfo() {
-    return compiler.findHelper(const SourceString('getRuntimeTypeInfo'));
+    return compiler.findHelper('getRuntimeTypeInfo');
   }
 
   Element getComputeSignature() {
-    return compiler.findHelper(const SourceString('computeSignature'));
+    return compiler.findHelper('computeSignature');
   }
 
   Element getGetRuntimeTypeArguments() {
-    return compiler.findHelper(const SourceString('getRuntimeTypeArguments'));
+    return compiler.findHelper('getRuntimeTypeArguments');
   }
 
   Element getGetRuntimeTypeArgument() {
-    return compiler.findHelper(const SourceString('getRuntimeTypeArgument'));
+    return compiler.findHelper('getRuntimeTypeArgument');
   }
 
   Element getRuntimeTypeToString() {
-    return compiler.findHelper(const SourceString('runtimeTypeToString'));
+    return compiler.findHelper('runtimeTypeToString');
   }
 
   Element getCheckSubtype() {
-    return compiler.findHelper(const SourceString('checkSubtype'));
+    return compiler.findHelper('checkSubtype');
   }
 
   Element getAssertSubtype() {
-    return compiler.findHelper(const SourceString('assertSubtype'));
+    return compiler.findHelper('assertSubtype');
   }
 
   Element getCheckSubtypeOfRuntimeType() {
-    return compiler.findHelper(const SourceString('checkSubtypeOfRuntimeType'));
+    return compiler.findHelper('checkSubtypeOfRuntimeType');
   }
 
   Element getAssertSubtypeOfRuntimeType() {
-    return compiler.findHelper(
-        const SourceString('assertSubtypeOfRuntimeType'));
+    return compiler.findHelper('assertSubtypeOfRuntimeType');
   }
 
   Element getCheckFunctionSubtype() {
-    return compiler.findHelper(const SourceString('checkFunctionSubtype'));
+    return compiler.findHelper('checkFunctionSubtype');
   }
 
   Element getThrowNoSuchMethod() {
-    return compiler.findHelper(const SourceString('throwNoSuchMethod'));
+    return compiler.findHelper('throwNoSuchMethod');
   }
 
   Element getCreateRuntimeType() {
-    return compiler.findHelper(const SourceString('createRuntimeType'));
+    return compiler.findHelper('createRuntimeType');
   }
 
   Element getFallThroughError() {
-    return compiler.findHelper(const SourceString("getFallThroughError"));
+    return compiler.findHelper("getFallThroughError");
   }
 
   Element getCreateInvocationMirror() {
@@ -1604,7 +1568,7 @@
   }
 
   Element getCyclicThrowHelper() {
-    return compiler.findHelper(const SourceString("throwCyclicInit"));
+    return compiler.findHelper("throwCyclicInit");
   }
 
   bool isNullImplementation(ClassElement cls) {
@@ -1663,10 +1627,10 @@
   bool shouldRetainSetter(Element element) => isNeededForReflection(element);
 
   /// Should [name] be retained for reflection?
-  bool shouldRetainName(SourceString name) {
+  bool shouldRetainName(String name) {
     if (hasInsufficientMirrorsUsed) return mustPreserveNames;
-    if (name == const SourceString('')) return false;
-    return symbolsUsed.contains(name.slowToString());
+    if (name == '') return false;
+    return symbolsUsed.contains(name);
   }
 
   bool get rememberLazies => isTreeShakingDisabled;
@@ -1687,12 +1651,12 @@
   Future onLibraryLoaded(LibraryElement library, Uri uri) {
     if (uri == Uri.parse('dart:_js_mirrors')) {
       disableTreeShakingMarker =
-          library.find(const SourceString('disableTreeShaking'));
+          library.find('disableTreeShaking');
       preserveMetadataMarker =
-          library.find(const SourceString('preserveMetadata'));
+          library.find('preserveMetadata');
     } else if (uri == Uri.parse('dart:_js_names')) {
       preserveNamesMarker =
-          library.find(const SourceString('preserveNames'));
+          library.find('preserveNames');
     }
     return new Future.value();
   }
@@ -1745,9 +1709,9 @@
     /// Record the name of [element] in [symbolsUsed]. Return true for
     /// convenience.
     bool registerNameOf(Element element) {
-      symbolsUsed.add(element.name.slowToString());
+      symbolsUsed.add(element.name);
       if (element.isConstructor()) {
-        symbolsUsed.add(element.getEnclosingClass().name.slowToString());
+        symbolsUsed.add(element.getEnclosingClass().name);
       }
       return true;
     }
@@ -1811,7 +1775,7 @@
 
     List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record];
     FunctionElement helper =
-        compiler.findHelper(const SourceString('isJsIndexable'));
+        compiler.findHelper('isJsIndexable');
     String helperName = namer.isolateAccess(helper);
     return new jsAst.Call(new jsAst.VariableUse(helperName), arguments);
   }
@@ -1846,6 +1810,13 @@
       metadataConstants.clear();
     }
 
+    if (isTreeShakingDisabled) {
+      if (enqueuer.isResolutionQueue) {
+        typeVariableHandler.onResolutionQueueEmpty(enqueuer);
+      } else {
+        typeVariableHandler.onCodegenQueueEmpty();
+      }
+    }
     customElementsAnalysis.onQueueEmpty(enqueuer);
   }
 }
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 bd5c8aa..04f983b 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -242,7 +242,7 @@
     }
 
     ClassElement classElement = constant.type.element;
-    SourceString className = classElement.name;
+    String className = classElement.name;
 
     List<jsAst.Expression> arguments = <jsAst.Expression>[];
 
@@ -311,7 +311,7 @@
   jsAst.Expression visitConstructed(ConstructedConstant constant) {
     Element element = constant.type.element;
     if (element.isForeign(compiler)
-        && element.name == const SourceString('JS_CONST')) {
+        && element.name == 'JS_CONST') {
       StringConstant str = constant.fields[0];
       return new jsAst.LiteralExpression(str.value.slowToString());
     }
@@ -338,7 +338,8 @@
       RuntimeTypes rti = backend.rti;
       Iterable<String> arguments = interface.typeArguments
           .toList(growable: false)
-          .map((DartType type) => rti.getTypeRepresentation(type, (_){}));
+          .map((DartType type) =>
+              rti.getTypeRepresentationWithHashes(type, (_){}));
       jsAst.Expression argumentList =
           new jsAst.LiteralString('[${arguments.join(', ')}]');
       return new jsAst.Call(getHelperProperty(backend.getSetRuntimeTypeInfo()),
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart
index 84d65cd..8e94149 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart
@@ -31,7 +31,7 @@
   const JavaScriptBinaryBitOperation(this.dartBitOperation);
 
   bool isUserDefinable() => dartBitOperation.isUserDefinable();
-  SourceString get name => dartBitOperation.name;
+  String get name => dartBitOperation.name;
 
   Constant fold(Constant left, Constant right) {
     // In JavaScript we don't check for -0 and treat it as if it was zero.
@@ -80,7 +80,7 @@
   const JavaScriptNegateOperation();
 
   bool isUserDefinable() => dartNegateOperation.isUserDefinable();
-  SourceString get name => dartNegateOperation.name;
+  String get name => dartNegateOperation.name;
 
   Constant fold(Constant constant) {
     if (constant.isInt()) {
@@ -100,7 +100,7 @@
   const JavaScriptBinaryArithmeticOperation(this.dartArithmeticOperation);
 
   bool isUserDefinable() => dartArithmeticOperation.isUserDefinable();
-  SourceString get name => dartArithmeticOperation.name;
+  String get name => dartArithmeticOperation.name;
 
   Constant fold(Constant left, Constant right) {
     Constant result = dartArithmeticOperation.fold(left, right);
@@ -117,7 +117,7 @@
   const JavaScriptIdentityOperation();
 
   bool isUserDefinable() => dartIdentityOperation.isUserDefinable();
-  SourceString get name => dartIdentityOperation.name;
+  String get name => dartIdentityOperation.name;
 
   BoolConstant fold(Constant left, Constant right) {
     BoolConstant result = dartIdentityOperation.fold(left, right);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart b/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
index fe71b86..158c626 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
@@ -101,7 +101,7 @@
     if (!fetchedTableAccessorMethod) {
       fetchedTableAccessorMethod = true;
       tableAccessorMethod = compiler.findInterceptor(
-          const SourceString('findIndexForWebComponentType'));
+          'findIndexForWebComponentType');
     }
     if (element == tableAccessorMethod) {
       joinFor(enqueuer).demanded = true;
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 649c8dd..49c7121 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -10,7 +10,7 @@
 import '../closure.dart';
 import '../elements/elements.dart';
 import '../js_emitter/js_emitter.dart'
-    show Emitter, CodeEmitterTask, ClassBuilder;
+    show Emitter, CodeEmitterTask, ClassBuilder, MetadataEmitter;
 
 import '../dart2jslib.dart';
 import '../dart_types.dart';
@@ -31,4 +31,5 @@
 part 'namer.dart';
 part 'native_emitter.dart';
 part 'runtime_types.dart';
+part 'type_variable_handler.dart';
 part 'custom_elements_analysis.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
index 093a2d0..9b5c56e 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
@@ -39,11 +39,11 @@
     return freshName;
   }
 
-  SourceString getClosureVariableName(SourceString name, int id) {
+  String getClosureVariableName(String name, int id) {
     if (id < ALPHABET_CHARACTERS) {
-      return new SourceString(new String.fromCharCodes([_letterNumber(id)]));
+      return new String.fromCharCodes([_letterNumber(id)]);
     }
-    return new SourceString("${getMappedInstanceName('closure')}_$id");
+    return "${getMappedInstanceName('closure')}_$id";
   }
 
   void reserveBackendNames() {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index f11ac3b..4a0098e 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -275,7 +275,7 @@
    * [STATIC_CLOSURE_NAME_NAME].
    */
   String get STATIC_CLOSURE_NAME_NAME => r'$name';
-  SourceString get closureInvocationSelectorName => Compiler.CALL_OPERATOR_NAME;
+  String get closureInvocationSelectorName => Compiler.CALL_OPERATOR_NAME;
   bool get shouldMinify => false;
 
   String getNameForJsGetName(Node node, String name) {
@@ -339,13 +339,13 @@
   }
 
   /**
-   * If the [name] is not private returns [:name.slowToString():]. Otherwise
+   * If the [name] is not private returns [:name:]. Otherwise
    * mangles the [name] so that each library has a unique name.
    */
-  String privateName(LibraryElement library, SourceString name) {
+  String privateName(LibraryElement library, String name) {
     // Public names are easy.
-    String nameString = name.slowToString();
-    if (!name.isPrivate()) return nameString;
+    String nameString = name;
+    if (!isPrivateName(name)) return nameString;
 
     // The first library asking for a short private name wins.
     LibraryElement owner = shouldMinify
@@ -365,9 +365,9 @@
   }
 
   String instanceMethodName(FunctionElement element) {
-    SourceString elementName = element.name;
-    SourceString name = operatorNameToIdentifier(elementName);
-    if (name != elementName) return getMappedOperatorName(name.slowToString());
+    String elementName = element.name;
+    String name = operatorNameToIdentifier(elementName);
+    if (name != elementName) return getMappedOperatorName(name);
 
     LibraryElement library = element.getLibrary();
     if (element.isGenerativeConstructorBody()) {
@@ -380,7 +380,7 @@
         !signature.optionalParameters.isEmpty) {
       StringBuffer buffer = new StringBuffer();
       signature.orderedOptionalParameters.forEach((Element element) {
-        buffer.write('\$${safeName(element.name.slowToString())}');
+        buffer.write('\$${safeName(element.name)}');
       });
       methodName = '$methodName$buffer';
     }
@@ -388,11 +388,11 @@
     return getMappedInstanceName(methodName);
   }
 
-  String publicInstanceMethodNameByArity(SourceString name, int arity) {
-    SourceString newName = operatorNameToIdentifier(name);
-    if (newName != name) return getMappedOperatorName(newName.slowToString());
-    assert(!name.isPrivate());
-    var base = name.slowToString();
+  String publicInstanceMethodNameByArity(String name, int arity) {
+    String newName = operatorNameToIdentifier(name);
+    if (newName != name) return getMappedOperatorName(newName);
+    assert(!isPrivateName(name));
+    var base = name;
     // We don't mangle the closure invoking function name because it
     // is generated by string concatenation in applyFunction from
     // js_helper.dart.
@@ -409,24 +409,24 @@
       String proposedName = privateName(selector.library, selector.name);
       return '$setterPrefix${getMappedInstanceName(proposedName)}';
     } else {
-      SourceString name = selector.name;
+      String name = selector.name;
       if (selector.kind == SelectorKind.OPERATOR
           || selector.kind == SelectorKind.INDEX) {
         name = operatorNameToIdentifier(name);
         assert(name != selector.name);
-        return getMappedOperatorName(name.slowToString());
+        return getMappedOperatorName(name);
       }
       assert(name == operatorNameToIdentifier(name));
       StringBuffer buffer = new StringBuffer();
-      for (SourceString argumentName in selector.getOrderedNamedArguments()) {
-        buffer.write('\$${safeName(argumentName.slowToString())}');
+      for (String argumentName in selector.getOrderedNamedArguments()) {
+        buffer.write('\$${safeName(argumentName)}');
       }
       String suffix = '\$${selector.argumentCount}$buffer';
       // We don't mangle the closure invoking function name because it
       // is generated by string concatenation in applyFunction from
       // js_helper.dart.
       if (selector.isClosureCall()) {
-        return "${name.slowToString()}$suffix";
+        return "$name$suffix";
       } else {
         String proposedName = privateName(selector.library, name);
         return getMappedInstanceName('$proposedName$suffix');
@@ -479,10 +479,10 @@
     return '$setterPrefix$name';
   }
 
-  String publicGetterName(SourceString name) {
+  String publicGetterName(String name) {
     // We dynamically create getters from the field-name. The getter name must
     // therefore be derived from the instance field-name.
-    String fieldName = getMappedInstanceName(name.slowToString());
+    String fieldName = getMappedInstanceName(name);
     return '$getterPrefix$fieldName';
   }
 
@@ -554,8 +554,8 @@
     return candidate;
   }
 
-  SourceString getClosureVariableName(SourceString name, int id) {
-    return new SourceString("${name.slowToString()}_$id");
+  String getClosureVariableName(String name, int id) {
+    return "${name}_$id";
   }
 
   /**
@@ -566,20 +566,20 @@
     assert(!element.isInstanceMember());
     String name;
     if (element.isGenerativeConstructor()) {
-      name = "${element.getEnclosingClass().name.slowToString()}\$"
-             "${element.name.slowToString()}";
+      name = "${element.getEnclosingClass().name}\$"
+             "${element.name}";
     } else if (element.isFactoryConstructor()) {
       // TODO(johnniwinther): Change factory name encoding as to not include
       // the class-name twice.
-      String className = element.getEnclosingClass().name.slowToString();
+      String className = element.getEnclosingClass().name;
       name = '${className}_${Elements.reconstructConstructorName(element)}';
     } else if (Elements.isStaticOrTopLevel(element)) {
       if (element.isMember()) {
         ClassElement enclosingClass = element.getEnclosingClass();
-        name = "${enclosingClass.name.slowToString()}_"
-               "${element.name.slowToString()}";
+        name = "${enclosingClass.name}_"
+               "${element.name}";
       } else {
-        name = element.name.slowToString().replaceAll('+', '_');
+        name = element.name.replaceAll('+', '_');
       }
     } else if (element.isLibrary()) {
       LibraryElement library = element;
@@ -593,7 +593,7 @@
             : name.substring(0, name.indexOf('.'));
       }
     } else {
-      name = element.name.slowToString();
+      name = element.name;
     }
     return name;
   }
@@ -610,7 +610,7 @@
       if (cls == backend.jsNullClass) return "u";
       if (cls == backend.jsBoolClass) return "b";
       if (cls == backend.jsInterceptorClass) return "I";
-      return cls.name.slowToString();
+      return cls.name;
     }
     List<String> names = classes
         .where((cls) => !Elements.isNativeOrExtendsNative(cls))
@@ -635,7 +635,7 @@
       return getNameOfInstanceMember(element);
     }
     String suffix = getInterceptorSuffix(classes);
-    return getMappedGlobalName("${element.name.slowToString()}\$$suffix");
+    return getMappedGlobalName("${element.name}\$$suffix");
   }
 
   String getOneShotInterceptorName(Selector selector,
@@ -960,51 +960,48 @@
   String safeName(String name) => _safeName(name, jsReserved);
   String safeVariableName(String name) => _safeName(name, jsVariableReserved);
 
-  SourceString operatorNameToIdentifier(SourceString name) {
+  String operatorNameToIdentifier(String name) {
     if (name == null) return null;
-    String value = name.stringValue;
-    if (value == null) {
-      return name;
-    } else if (value == '==') {
-      return const SourceString(r'$eq');
-    } else if (value == '~') {
-      return const SourceString(r'$not');
-    } else if (value == '[]') {
-      return const SourceString(r'$index');
-    } else if (value == '[]=') {
-      return const SourceString(r'$indexSet');
-    } else if (value == '*') {
-      return const SourceString(r'$mul');
-    } else if (value == '/') {
-      return const SourceString(r'$div');
-    } else if (value == '%') {
-      return const SourceString(r'$mod');
-    } else if (value == '~/') {
-      return const SourceString(r'$tdiv');
-    } else if (value == '+') {
-      return const SourceString(r'$add');
-    } else if (value == '<<') {
-      return const SourceString(r'$shl');
-    } else if (value == '>>') {
-      return const SourceString(r'$shr');
-    } else if (value == '>=') {
-      return const SourceString(r'$ge');
-    } else if (value == '>') {
-      return const SourceString(r'$gt');
-    } else if (value == '<=') {
-      return const SourceString(r'$le');
-    } else if (value == '<') {
-      return const SourceString(r'$lt');
-    } else if (value == '&') {
-      return const SourceString(r'$and');
-    } else if (value == '^') {
-      return const SourceString(r'$xor');
-    } else if (value == '|') {
-      return const SourceString(r'$or');
-    } else if (value == '-') {
-      return const SourceString(r'$sub');
-    } else if (value == 'unary-') {
-      return const SourceString(r'$negate');
+    if (name == '==') {
+      return r'$eq';
+    } else if (name == '~') {
+      return r'$not';
+    } else if (name == '[]') {
+      return r'$index';
+    } else if (name == '[]=') {
+      return r'$indexSet';
+    } else if (name == '*') {
+      return r'$mul';
+    } else if (name == '/') {
+      return r'$div';
+    } else if (name == '%') {
+      return r'$mod';
+    } else if (name == '~/') {
+      return r'$tdiv';
+    } else if (name == '+') {
+      return r'$add';
+    } else if (name == '<<') {
+      return r'$shl';
+    } else if (name == '>>') {
+      return r'$shr';
+    } else if (name == '>=') {
+      return r'$ge';
+    } else if (name == '>') {
+      return r'$gt';
+    } else if (name == '<=') {
+      return r'$le';
+    } else if (name == '<') {
+      return r'$lt';
+    } else if (name == '&') {
+      return r'$and';
+    } else if (name == '^') {
+      return r'$xor';
+    } else if (name == '|') {
+      return r'$or';
+    } else if (name == '-') {
+      return r'$sub';
+    } else if (name == 'unary-') {
+      return r'$negate';
     } else {
       return name;
     }
@@ -1097,7 +1094,7 @@
   }
 
   visitFunction(FunctionConstant constant) {
-    add(constant.element.name.slowToString());
+    add(constant.element.name);
   }
 
   visitNull(NullConstant constant) {
@@ -1159,7 +1156,7 @@
   }
 
   visitConstructed(ConstructedConstant constant) {
-    addRoot(constant.type.element.name.slowToString());
+    addRoot(constant.type.element.name);
     for (int i = 0; i < constant.fields.length; i++) {
       _visit(constant.fields[i]);
       if (failed) return;
@@ -1175,7 +1172,7 @@
   }
 
   visitInterceptor(InterceptorConstant constant) {
-    addRoot(constant.dispatchedType.element.name.slowToString());
+    addRoot(constant.dispatchedType.element.name);
     add('methods');
   }
 }
@@ -1215,7 +1212,7 @@
   int visitFalse(FalseConstant constant) => 3;
 
   int visitFunction(FunctionConstant constant) {
-    return _hashString(1, constant.element.name.slowToString());
+    return _hashString(1, constant.element.name);
   }
 
   int visitInt(IntConstant constant) => _hashInt(constant.value);
@@ -1236,7 +1233,7 @@
   }
 
   int visitConstructed(ConstructedConstant constant) {
-    int hash = _hashString(3, constant.type.element.name.slowToString());
+    int hash = _hashString(3, constant.type.element.name);
     for (int i = 0; i < constant.fields.length; i++) {
       hash = _combine(hash, _visit(constant.fields[i]));
     }
@@ -1251,7 +1248,7 @@
   }
 
   visitInterceptor(InterceptorConstant constant) {
-    String typeName = constant.dispatchedType.element.name.slowToString();
+    String typeName = constant.dispatchedType.element.name;
     return _hashString(5, typeName);
   }
 
@@ -1344,7 +1341,7 @@
   }
 
   visitType(DartType type, _) {
-    sb.write(type.name.slowToString());
+    sb.write(type.name);
   }
 
   visitFunctionType(FunctionType type, _) {
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 afde0a1..d7c0b4e 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -40,68 +40,37 @@
   String get N => emitter.N;
 
   String get dynamicName {
-    Element element = compiler.findHelper(
-        const SourceString('dynamicFunction'));
+    Element element = compiler.findHelper('dynamicFunction');
     return backend.namer.isolateAccess(element);
   }
 
   String get dynamicFunctionTableName {
-    Element element = compiler.findHelper(
-        const SourceString('dynamicFunctionTable'));
+    Element element = compiler.findHelper('dynamicFunctionTable');
     return backend.namer.isolateAccess(element);
   }
 
   String get typeNameOfName {
-    Element element = compiler.findHelper(
-        const SourceString('getTypeNameOf'));
+    Element element = compiler.findHelper('getTypeNameOf');
     return backend.namer.isolateAccess(element);
   }
 
   String get defPropName {
-    Element element = compiler.findHelper(
-        const SourceString('defineProperty'));
+    Element element = compiler.findHelper('defineProperty');
     return backend.namer.isolateAccess(element);
   }
 
   String get toStringHelperName {
-    Element element = compiler.findHelper(
-        const SourceString('toStringForNativeObject'));
+    Element element = compiler.findHelper('toStringForNativeObject');
     return backend.namer.isolateAccess(element);
   }
 
   String get hashCodeHelperName {
-    Element element = compiler.findHelper(
-        const SourceString('hashCodeForNativeObject'));
+    Element element = compiler.findHelper('hashCodeForNativeObject');
     return backend.namer.isolateAccess(element);
   }
 
   String get dispatchPropertyNameVariable {
-    Element element = compiler.findInterceptor(
-        const SourceString('dispatchPropertyName'));
-    return backend.namer.isolateAccess(element);
-  }
-
-  String get defineNativeMethodsName {
-    Element element = compiler.findHelper(
-        const SourceString('defineNativeMethods'));
-    return backend.namer.isolateAccess(element);
-  }
-
-  String get defineNativeMethodsNonleafName {
-    Element element = compiler.findHelper(
-        const SourceString('defineNativeMethodsNonleaf'));
-    return backend.namer.isolateAccess(element);
-  }
-
-  String get defineNativeMethodsExtendedName {
-    Element element = compiler.findHelper(
-        const SourceString('defineNativeMethodsExtended'));
-    return backend.namer.isolateAccess(element);
-  }
-
-  String get defineNativeMethodsFinishName {
-    Element element = compiler.findHelper(
-        const SourceString('defineNativeMethodsFinish'));
+    Element element = compiler.findInterceptor('dispatchPropertyName');
     return backend.namer.isolateAccess(element);
   }
 
@@ -109,7 +78,7 @@
   // tags (having JavaScript identifier syntax) and directives that begin with
   // `!`.
   List<String> nativeTagsOfClassRaw(ClassElement cls) {
-    String quotedName = cls.nativeTagInfo.slowToString();
+    String quotedName = cls.nativeTagInfo;
     return quotedName.substring(1, quotedName.length - 1).split(',');
   }
 
@@ -253,28 +222,59 @@
       }
     }
 
-    // Emit code to set up dispatch data that maps tags to the interceptors, but
-    // only if native classes are actually instantiated.
+    // Add properties containing the information needed to construct maps used
+    // by getNativeInterceptor and custom elements.
     if (compiler.enqueuer.codegen.nativeEnqueuer
         .hasInstantiatedNativeClasses()) {
-      void generateDefines(ClassElement classElement) {
-        generateDefineNativeMethods(leafTags[classElement],
-            null,
-            classElement, defineNativeMethodsName);
+      void generateClassInfo(ClassElement classElement) {
+        // Property has the form:
+        //
+        //    "%": "leafTag1|leafTag2|...;nonleafTag1|...;Class1|Class2|...",
+        //
+        // If there is no data following a semicolon, the semicolon can be
+        // omitted.
+
+        String formatTags(Iterable<String> tags) {
+          if (tags == null) return '';
+          return (tags.toList()..sort()).join('|');
+        }
+
         List<ClassElement> extensions = extensionPoints[classElement];
-        if (extensions == null) {
-          generateDefineNativeMethods(nonleafTags[classElement],
-              null,
-              classElement, defineNativeMethodsNonleafName);
+
+        String leafStr = formatTags(leafTags[classElement]);
+        String nonleafStr = formatTags(nonleafTags[classElement]);
+
+        StringBuffer sb = new StringBuffer(leafStr);
+        if (nonleafStr != '') {
+          sb..write(';')..write(nonleafStr);
+        }
+        if (extensions != null) {
+          sb..write(';')
+            ..writeAll(extensions.map(backend.namer.getNameOfClass), '|');
+        }
+        String encoding = sb.toString();
+
+        ClassBuilder builder = builders[classElement];
+        if (builder == null) {
+          // 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');
+          }
         } else {
-          generateDefineNativeMethods(nonleafTags[classElement],
-              makeSubclassList(extensions),
-              classElement, defineNativeMethodsExtendedName);
+          builder.addProperty('%', js.string(encoding));
         }
       }
-      generateDefines(backend.jsInterceptorClass);
+      generateClassInfo(backend.jsInterceptorClass);
       for (ClassElement classElement in classes) {
-        generateDefines(classElement);
+        generateClassInfo(classElement);
       }
     }
 
@@ -358,38 +358,10 @@
     return builder;
   }
 
-  void generateDefineNativeMethods(
-      Set<String> tags, jsAst.Expression extraArgument,
-      ClassElement classElement, String definer) {
-    if (tags == null) return;
-    String tagsString = (tags.toList()..sort()).join('|');
-
-    List arguments = [
-        js.string(tagsString),
-        js(backend.namer.isolateAccess(classElement))];
-    if (extraArgument != null) {
-      arguments.add(extraArgument);
-    }
-    jsAst.Expression definition = js(definer)(arguments);
-
-    nativeBuffer.add(jsAst.prettyPrint(definition, compiler));
-    nativeBuffer.add('$N$n');
-  }
-
-  jsAst.Expression makeSubclassList(List<ClassElement> classes) {
-    return new jsAst.ArrayInitializer.from(
-        classes.map((ClassElement classElement) =>
-            js(backend.namer.isolateAccess(classElement))));
-  }
-
   void finishGenerateNativeClasses() {
     // TODO(sra): Put specialized version of getNativeMethods on
     // `Object.prototype` to avoid checking in `getInterceptor` and
     // specializations.
-
-    // jsAst.Expression call = js(defineNativeMethodsFinishName)([]);
-    // nativeBuffer.add(jsAst.prettyPrint(call, compiler));
-    // nativeBuffer.add('$N$n');
   }
 
   void potentiallyConvertDartClosuresToJs(
@@ -398,12 +370,12 @@
       List<jsAst.Parameter> stubParameters) {
     FunctionSignature parameters = member.computeSignature(compiler);
     Element converter =
-        compiler.findHelper(const SourceString('convertDartClosureToJS'));
+        compiler.findHelper('convertDartClosureToJS');
     String closureConverter = backend.namer.isolateAccess(converter);
     Set<String> stubParameterNames = new Set<String>.from(
         stubParameters.map((param) => param.name));
     parameters.forEachParameter((Element parameter) {
-      String name = parameter.name.slowToString();
+      String name = parameter.name;
       // If [name] is not in [stubParameters], then the parameter is an optional
       // parameter that was not provided for this stub.
       for (jsAst.Parameter stubParameter in stubParameters) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index 8f92771..1669563 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -485,7 +485,7 @@
     int index = 0;
     for (; !types.isEmpty; types = types.tail, index++) {
       jsAst.Expression representation =
-          _getTypeRepresentation(types.head, onVariable);
+          getTypeRepresentation(types.head, onVariable);
       elements.add(new jsAst.ArrayElement(index, representation));
     }
     return new jsAst.ArrayInitializer(index, elements);
@@ -495,9 +495,9 @@
                                    {bool alwaysGenerateFunction: false}) {
     ClassElement contextClass = Types.getClassContext(type);
     jsAst.Expression onVariable(TypeVariableType v) {
-      return new jsAst.VariableUse(v.name.slowToString());
+      return new jsAst.VariableUse(v.name);
     };
-    jsAst.Expression encoding = _getTypeRepresentation(type, onVariable);
+    jsAst.Expression encoding = getTypeRepresentation(type, onVariable);
     if (contextClass == null && !alwaysGenerateFunction) {
       return encoding;
     } else {
@@ -529,18 +529,19 @@
     }
   }
 
-  String getTypeRepresentation(DartType type, OnVariableCallback onVariable) {
+  String getTypeRepresentationWithHashes(DartType type,
+                                         OnVariableCallback onVariable) {
     // Create a type representation.  For type variables call the original
     // callback for side effects and return a template placeholder.
-    jsAst.Expression representation = _getTypeRepresentation(type, (variable) {
+    jsAst.Expression representation = getTypeRepresentation(type, (variable) {
       onVariable(variable);
       return new jsAst.LiteralString('#');
     });
     return jsAst.prettyPrint(representation, compiler).buffer.toString();
   }
 
-  jsAst.Expression _getTypeRepresentation(DartType type,
-                                          OnVariableCallback onVariable) {
+  jsAst.Expression getTypeRepresentation(DartType type,
+                                         OnVariableCallback onVariable) {
     return representationGenerator.getTypeRepresentation(type, onVariable);
   }
 
@@ -653,11 +654,11 @@
     }
     if (!type.namedParameterTypes.isEmpty) {
       List<jsAst.Property> namedArguments = <jsAst.Property>[];
-      Link<SourceString> names = type.namedParameters;
+      Link<String> names = type.namedParameters;
       Link<DartType> types = type.namedParameterTypes;
       while (!types.isEmpty) {
         assert(!names.isEmpty);
-        jsAst.Expression name = js.string(names.head.slowToString());
+        jsAst.Expression name = js.string(names.head);
         namedArguments.add(new jsAst.Property(name, visit(types.head)));
         names = names.tail;
         types = types.tail;
@@ -704,8 +705,7 @@
     StringBuffer sb = new StringBuffer();
     for (ClassElement holder in this) {
       for (ClassElement check in [holder]) {
-        sb.write('${holder.name.slowToString()}.'
-                 '${check.name.slowToString()}, ');
+        sb.write('${holder.name}.' '${check.name}, ');
       }
     }
     return '[$sb]';
@@ -820,12 +820,12 @@
   jsAst.Expression getCode(RuntimeTypes rti, bool ensureIsFunction) {
     jsAst.Expression declaration(TypeVariableType variable) {
       return new jsAst.Parameter(
-          rti.backend.namer.safeVariableName(variable.name.slowToString()));
+          rti.backend.namer.safeVariableName(variable.name));
     }
 
     jsAst.Expression use(TypeVariableType variable) {
       return new jsAst.VariableUse(
-          rti.backend.namer.safeVariableName(variable.name.slowToString()));
+          rti.backend.namer.safeVariableName(variable.name));
     }
 
     jsAst.Expression value =
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart b/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
new file mode 100644
index 0000000..0380bed
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
@@ -0,0 +1,156 @@
+// 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 js_backend;
+
+/**
+ * Handles construction of TypeVariable constants needed at runtime.
+ */
+class TypeVariableHandler {
+  JavaScriptBackend backend;
+  FunctionElement typeVariableConstructor;
+  CompileTimeConstantEvaluator evaluator;
+
+  /**
+   * Contains all instantiated classes that have type variables and are needed
+   * for reflection.
+   */
+  List<ClassElement> typeVariableClasses = new List<ClassElement>();
+
+  /**
+   *  Maps a class element to a list with indices that point to type variables
+   *  constants for each of the class' type variables.
+   */
+  Map<ClassElement, List<int>> typeVariables =
+      new Map<ClassElement, List<int>>();
+
+  /**
+   *  Maps a TypeVariableType to the index pointing to the constant representing
+   *  the corresponding type variable at runtime.
+   */
+  Map<TypeVariableElement, int> typeVariableConstants =
+      new Map<TypeVariableElement, int>();
+
+  TypeVariableHandler(this.backend);
+
+  ClassElement get typeVariableClass => backend.typeVariableClass;
+  CodeEmitterTask get task => backend.emitter;
+  MetadataEmitter get emitter => task.metadataEmitter;
+  Compiler get compiler => backend.compiler;
+
+  void registerClassWithTypeVariables(ClassElement cls) {
+    typeVariableClasses.add(cls);
+  }
+
+  void onResolutionQueueEmpty(Enqueuer enqueuer) {
+    if (typeVariableConstructor == null) {
+      if (!typeVariableClass.constructors.isEmpty &&
+          !typeVariableClass.constructors.tail.isEmpty) {
+        compiler.reportInternalError(
+            typeVariableClass,
+            'Class $typeVariableClass should only have one constructor');
+      }
+      typeVariableConstructor = typeVariableClass.constructors.head;
+      backend.enqueueClass(
+          enqueuer, typeVariableClass, compiler.globalDependencies);
+      backend.enqueueInResolution(
+          typeVariableConstructor, compiler.globalDependencies);
+    }
+  }
+
+  void onCodegenQueueEmpty() {
+    evaluator = new CompileTimeConstantEvaluator(
+        compiler.constantHandler, compiler.globalDependencies, compiler);
+
+    for (ClassElement cls in typeVariableClasses) {
+      // TODO(zarah): Running through all the members is suboptimal. Change this
+      // as part of marking elements for reflection.
+      bool hasMemberNeededForReflection(ClassElement cls) {
+        bool result = false;
+        cls.implementation.forEachMember((ClassElement cls, Element member) {
+          result = result || backend.isNeededForReflection(member);
+        });
+        return result;
+      }
+
+      if (!backend.isNeededForReflection(cls) &&
+          !hasMemberNeededForReflection(cls)) continue;
+
+      InterfaceType typeVariableType = typeVariableClass.computeType(compiler);
+      List<int> constants = <int>[];
+      for (TypeVariableType currentTypeVariable in cls.typeVariables) {
+        List<Constant> createArguments(FunctionElement constructor) {
+        if (constructor != typeVariableConstructor) {
+            compiler.internalErrorOnElement(
+                currentTypeVariable.element,
+                'Unexpected constructor $constructor');
+          }
+          Constant name = backend.constantSystem.createString(
+              new DartString.literal(currentTypeVariable.name),
+              null);
+          Constant bound = backend.constantSystem.createInt(
+              emitter.reifyType(currentTypeVariable.element.bound));
+          Constant type = evaluator.makeTypeConstant(cls);
+          return [type, name, bound];
+        }
+
+        Constant c = evaluator.makeConstructedConstant(
+            currentTypeVariable.element, typeVariableType,
+            typeVariableConstructor, createArguments);
+        backend.registerCompileTimeConstant(c, compiler.globalDependencies);
+        compiler.constantHandler.addCompileTimeConstantForEmission(c);
+        constants.add(
+            reifyTypeVariableConstant(c, currentTypeVariable.element));
+      }
+      typeVariables[cls] = constants;
+    }
+    typeVariableClasses.clear();
+  }
+
+  /**
+   * Adds [c] to [emitter.globalMetadata] and returns the index pointing to
+   * the entry.
+   *
+   * If the corresponding type variable has already been encountered an
+   * entry in the list has already been reserved and the constant is added
+   * there, otherwise a new entry for [c] is created.
+   */
+  int reifyTypeVariableConstant(Constant c, TypeVariableElement variable) {
+    String name =
+        jsAst.prettyPrint(task.constantReference(c), compiler).getText();
+    int index;
+    if (typeVariableConstants.containsKey(variable)) {
+      index = typeVariableConstants[variable];
+      emitter.globalMetadata[index] = name;
+    } else {
+      index = emitter.addGlobalMetadata(name);
+      typeVariableConstants[variable] = index;
+    }
+    return index;
+  }
+
+  /**
+   * Returns the index pointing to the constant in [emitter.globalMetadata]
+   * representing this type variable
+   *.
+   *
+   * If the constant has not yet been constructed, an entry is  allocated in
+   * the global metadata list and the index pointing to this entry is returned.
+   * When the corresponding constant is constructed later,
+   * [reifyTypeVariableConstant] will be called and the constant will be added
+   * on the allocated entry.
+   */
+  int reifyTypeVariable(TypeVariableElement variable) {
+    if (typeVariableConstants.containsKey(variable)) {
+      return typeVariableConstants[variable];
+    }
+
+    emitter.globalMetadata.add('Placeholder for ${variable}');
+    return typeVariableConstants[variable] = emitter.globalMetadata.length - 1;
+  }
+
+  List<int> typeVariablesOf(ClassElement classElement) {
+    return typeVariables[classElement];
+  }
+}
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 f483d23..53285fd 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
@@ -144,7 +144,7 @@
             metadata = new jsAst.LiteralNull();
           }
           fieldMetadata.add(metadata);
-          recordMangledField(field, accessorName, field.name.slowToString());
+          recordMangledField(field, accessorName, field.name);
           if (!needsAccessor) {
             // Emit field for constructor generation.
             assert(!classIsNative);
@@ -297,12 +297,10 @@
 
     if (backend.isNeededForReflection(classElement)) {
       Link typeVars = classElement.typeVariables;
-      List properties = [];
-      for (TypeVariableType typeVar in typeVars) {
-        properties.add(js.string(typeVar.name.slowToString()));
-        properties.add(
-            js.toExpression(
-                task.metadataEmitter.reifyType(typeVar.element.bound)));
+      Iterable properties = [];
+      if (task.typeVariableHandler.typeVariablesOf(classElement) != null) {
+        properties = task.typeVariableHandler.typeVariablesOf(classElement)
+            .map(js.toExpression);
       }
 
       ClassElement superclass = classElement.superclass;
@@ -349,11 +347,15 @@
     buffer.write(jsAst.prettyPrint(builder.toObjectInitializer(), compiler));
     String reflectionName = task.getReflectionName(classElement, className);
     if (reflectionName != null) {
-      List<int> interfaces = <int>[];
-      for (DartType interface in classElement.interfaces) {
-        interfaces.add(task.metadataEmitter.reifyType(interface));
+      if (!backend.isNeededForReflection(classElement)) {
+        buffer.write(',$n$n"+$reflectionName": 0');
+      } else {
+        List<int> interfaces = <int>[];
+        for (DartType interface in classElement.interfaces) {
+          interfaces.add(task.metadataEmitter.reifyType(interface));
+        }
+        buffer.write(',$n$n"+$reflectionName": $interfaces');
       }
-      buffer.write(',$n$n"+$reflectionName": $interfaces');
     }
   }
 
@@ -395,7 +397,7 @@
 
     void visitField(Element holder, VariableElement field) {
       assert(invariant(element, field.isDeclaration));
-      SourceString name = field.name;
+      String name = field.name;
 
       // Keep track of whether or not we're dealing with a field mixin
       // into a native class.
@@ -427,7 +429,7 @@
             : namer.getNameOfField(field);
         String fieldName = field.hasFixedBackendName()
             ? field.fixedBackendName()
-            : (isMixinNativeField ? name.slowToString() : accessorName);
+            : (isMixinNativeField ? name : accessorName);
         bool needsCheckedSetter = false;
         if (compiler.enableTypeAssertions
             && needsSetter
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/closure_invocation_element.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/closure_invocation_element.dart
index bd52fe2..0b891d0 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/closure_invocation_element.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/closure_invocation_element.dart
@@ -9,7 +9,7 @@
  * from the given element.
  */
 class ClosureInvocationElement extends FunctionElementX {
-  ClosureInvocationElement(SourceString name,
+  ClosureInvocationElement(String name,
                            FunctionElement other)
       : super.from(name, other, other.enclosingElement),
         methodElement = other;
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 31b3506..24f1ef2 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
@@ -43,6 +43,7 @@
   Set<ClassElement> instantiatedClasses;
 
   JavaScriptBackend get backend => compiler.backend;
+  TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;
 
   String get _ => space;
   String get space => compiler.enableMinification ? "" : " ";
@@ -384,6 +385,8 @@
       js('constructors = null'),
 
       js('var finishedClasses = {}'),
+      js('init.interceptorsByTag = {}'),
+      js('init.leafTags = {}'),
 
       buildFinishClass(),
     ];
@@ -434,7 +437,49 @@
              js('superConstructor ='
                     'existingIsolateProperties[superclass]')),
 
-      js('prototype = inheritFrom(constructor, superConstructor)'),
+      js('var prototype = inheritFrom(constructor, superConstructor)'),
+
+      optional(!nativeClasses.isEmpty,
+          // The property looks like this:
+          //
+          // HtmlElement: {
+          //     "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton"
+          //
+          // The first two semicolon-separated parts contain dispatch tags, the
+          // third contains the JavaScript names for classes.
+          //
+          // The tags indicate that JavaScript objects with the dispatch tags
+          // (usually constructor names) HTMLDivElement, HTMLAnchorElement and
+          // HTMLElement all map to the Dart native class named HtmlElement.
+          // The first set is for effective leaf nodes in the hierarchy, the
+          // second set is non-leaf nodes.
+          //
+          // The third part contains the JavaScript names of Dart classes that
+          // extend the native class. Here, FancyButton extends HtmlElement, so
+          // the runtime needs to know that window.HTMLElement.prototype is the
+          // prototype that needs to be extended in creating the custom element.
+          //
+          // 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_('nativeSpec[0]', [
+                  js('var tags = nativeSpec[0].split("|")'),
+                  js.for_('var i = 0', 'i < tags.length', 'i++', [
+                      js('init.interceptorsByTag[tags[i]] = constructor'),
+                      js('init.leafTags[tags[i]] = true')])]),
+              js.if_('nativeSpec[1]', [
+                  js('tags = nativeSpec[1].split("|")'),
+                  optional(true, // User subclassing of native classes?
+                      js.if_('nativeSpec[2]', [
+                          js('var subclasses = nativeSpec[2].split("|")'),
+                          js.for_('var i = 0', 'i < subclasses.length', 'i++', [
+                              js('var subclass = allClasses[subclasses[i]]'),
+                              js('subclass.\$nativeSuperclassTag = '
+                                 'tags[0]')])])),
+                  js.for_('i = 0', 'i < tags.length', 'i++', [
+                      js('init.interceptorsByTag[tags[i]] = constructor'),
+                      js('init.leafTags[tags[i]] = false')])])]))
     ]);
 
     return new jsAst.FunctionDeclaration(
@@ -578,9 +623,9 @@
   /// An anonymous mixin application has no reflection name.
   /// This is used by js_mirrors.dart.
   String getReflectionName(elementOrSelector, String mangledName) {
-    SourceString name = elementOrSelector.name;
+    String name = elementOrSelector.name;
     if (!backend.shouldRetainName(name)) {
-      if (name == const SourceString('') && elementOrSelector is Element) {
+      if (name == '' && elementOrSelector is Element) {
         // Make sure to retain names of unnamed constructors.
         if (!backend.isNeededForReflection(elementOrSelector)) return null;
       } else {
@@ -595,7 +640,7 @@
   }
 
   String getReflectionNameInternal(elementOrSelector, String mangledName) {
-    String name = elementOrSelector.name.slowToString();
+    String name = elementOrSelector.name;
     if (elementOrSelector.isGetter()) return name;
     if (elementOrSelector.isSetter()) {
       if (!mangledName.startsWith(namer.setterPrefix)) return '$name=';
@@ -663,7 +708,7 @@
     } else if (element.isClass()) {
       ClassElement cls = element;
       if (cls.isUnnamedMixinApplication) return null;
-      return cls.name.slowToString();
+      return cls.name;
     }
     throw compiler.internalErrorOnElement(
         element, 'Do not know how to reflect on this $element');
@@ -671,8 +716,7 @@
 
   String namedParametersAsReflectionNames(Selector selector) {
     if (selector.getOrderedNamedArguments().isEmpty) return '';
-    String names = selector.getOrderedNamedArguments().map(
-        (x) => x.slowToString()).join(':');
+    String names = selector.getOrderedNamedArguments().join(':');
     return ':$names';
   }
 
@@ -826,7 +870,7 @@
         // closure that constructs the initial value.
         List<jsAst.Expression> arguments = <jsAst.Expression>[];
         arguments.add(js(isolateProperties));
-        arguments.add(js.string(element.name.slowToString()));
+        arguments.add(js.string(element.name));
         arguments.add(js.string(namer.getNameX(element)));
         arguments.add(js.string(namer.getLazyInitializerName(element)));
         arguments.add(code);
@@ -1018,7 +1062,7 @@
     // classes to figure out if we need the support on any native
     // class. If so, we let the native emitter deal with it.
     if (compiler.enabledNoSuchMethod) {
-      SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD;
+      String noSuchMethodName = Compiler.NO_SUCH_METHOD;
       Selector noSuchMethodSelector = compiler.noSuchMethodSelector;
       for (ClassElement element in neededClasses) {
         if (!element.isNative()) continue;
@@ -1088,10 +1132,10 @@
 ''');
     if (DEBUG_FAST_OBJECTS) {
       ClassElement primitives =
-          compiler.findHelper(const SourceString('Primitives'));
+          compiler.findHelper('Primitives');
       FunctionElement printHelper =
           compiler.lookupElementIn(
-              primitives, const SourceString('printString'));
+              primitives, 'printString');
       String printHelperName = namer.isolateAccess(printHelper);
       mainBuffer.add('''
 // The following only works on V8 when run with option "--allow-natives-syntax".
@@ -1366,10 +1410,10 @@
       }
       if (DEBUG_FAST_OBJECTS) {
         ClassElement primitives =
-            compiler.findHelper(const SourceString('Primitives'));
+            compiler.findHelper('Primitives');
         FunctionElement printHelper =
             compiler.lookupElementIn(
-                primitives, const SourceString('printString'));
+                primitives, 'printString');
         String printHelperName = namer.isolateAccess(printHelper);
 
         mainBuffer.add('''
@@ -1548,7 +1592,10 @@
 
   void outputSourceMap(String code, String name) {
     if (!generateSourceMap) return;
-    SourceFile compiledFile = new SourceFile(null, compiler.assembledCode);
+    // Create a source file for the compilation output. This allows using
+    // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder].
+    SourceFile compiledFile =
+        new StringSourceFile(null, compiler.assembledCode);
     String sourceMap = buildSourceMap(mainBuffer, compiledFile);
     compiler.outputProvider(name, 'js.map')
         ..add(sourceMap)
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
index 1b2e54a..c14f3b1 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
@@ -41,7 +41,7 @@
       return;
     }
     ConstantHandler handler = compiler.constantHandler;
-    List<SourceString> names = selector.getOrderedNamedArguments();
+    List<String> names = selector.getOrderedNamedArguments();
 
     String invocationName = namer.invocationName(selector);
     if (alreadyGenerated.contains(invocationName)) return;
@@ -84,7 +84,7 @@
       // Use generic names for closures to facilitate code sharing.
       String jsName = member is ClosureInvocationElement
           ? 'p${parameterIndex++}'
-          : backend.namer.safeName(element.name.slowToString());
+          : backend.namer.safeName(element.name);
       assert(jsName != receiverArgumentName);
       if (count < optionalParameterStart) {
         parametersBuffer[count] = new jsAst.Parameter(jsName);
@@ -213,7 +213,7 @@
     // See Primities.applyFunction in js_helper.dart for details.
     List<jsAst.Property> properties = <jsAst.Property>[];
     for (Element element in signature.orderedOptionalParameters) {
-      String jsName = backend.namer.safeName(element.name.slowToString());
+      String jsName = backend.namer.safeName(element.name);
       Constant value = compiler.constantHandler.initialVariableValues[element];
       jsAst.Expression reference = null;
       if (value == null) {
@@ -240,7 +240,7 @@
                                element.name,
                                element.getLibrary(),
                                signature.requiredParameterCount,
-                               <SourceString>[]));
+                               <String>[]));
 
     // For each optional parameter, we increment the number of passed
     // argument.
@@ -249,7 +249,7 @@
                                  element.name,
                                  element.getLibrary(),
                                  signature.requiredParameterCount + i,
-                                 <SourceString>[]));
+                                 <String>[]));
     }
     return selectors;
   }
@@ -286,7 +286,7 @@
       assert(task.instantiatedClasses.contains(compiler.closureClass));
 
       ClassElement closureClassElement = new ClosureClassElement(
-          null, new SourceString(name), compiler, element,
+          null, name, compiler, element,
           element.getCompilationUnit());
       // Now add the methods on the closure class. The instance method does not
       // have the correct name. Since [addParameterStubs] use the name to create
@@ -411,7 +411,7 @@
         : 'BoundClosure\$${parameterCount}';
 
     ClassElement closureClassElement = new ClosureClassElement(
-        null, new SourceString(name), compiler, member,
+        null, name, compiler, member,
         member.getCompilationUnit());
     String superName = namer.getNameOfClass(closureClassElement.superclass);
 
@@ -621,7 +621,7 @@
       jsAst.Node defaultValues =
           task.metadataEmitter.reifyDefaultArguments(member);
       if (defaultValues != null) {
-        String unmangledName = member.name.slowToString();
+        String unmangledName = member.name;
         builder.addProperty('*$unmangledName', defaultValues);
       }
     }
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart
index e620aa2..0a458e4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart
@@ -220,7 +220,7 @@
     }
 
     if (selector.isOperator()) {
-      String name = selector.name.stringValue;
+      String name = selector.name;
       if (name == '==') {
         // Unfolds to:
         //    if (receiver == null) return a0 == null;
@@ -469,7 +469,7 @@
           for (Element member in analysis.constructors(classElement)) {
             properties.add(
                 new jsAst.Property(
-                    js.string(member.name.slowToString()),
+                    js.string(member.name),
                     new jsAst.VariableUse(
                         backend.namer.isolateAccess(member))));
           }
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/js_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/js_emitter.dart
index 229bf10..cf261ca 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/js_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/js_emitter.dart
@@ -36,10 +36,12 @@
     RuntimeTypes,
     Substitution,
     TypeCheck,
-    TypeChecks;
+    TypeChecks,
+    TypeVariableHandler;
 
 import '../source_file.dart' show
-    SourceFile;
+    SourceFile,
+    StringSourceFile;
 
 import '../source_map_builder.dart' show
     SourceMapBuilder;
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/metadata_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/metadata_emitter.dart
index f4597f3..6fb21d3 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/metadata_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/metadata_emitter.dart
@@ -70,13 +70,18 @@
   }
 
   int reifyType(DartType type) {
-    // TODO(ahe): Handle type variables correctly instead of using "#".
-    String representation = backend.rti.getTypeRepresentation(type, (_) {});
-    return addGlobalMetadata(representation.replaceAll('#', 'null'));
+    jsAst.Expression representation =
+        backend.rti.getTypeRepresentation(type, (variable) {
+          return js.toExpression(
+              task.typeVariableHandler.reifyTypeVariable(variable.element));
+        });
+
+    return addGlobalMetadata(
+        jsAst.prettyPrint(representation, compiler).getText());
   }
 
-  int reifyName(SourceString name) {
-    return addGlobalMetadata('"${name.slowToString()}"');
+  int reifyName(String name) {
+    return addGlobalMetadata('"$name"');
   }
 
   int addGlobalMetadata(String string) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
index 8b565f5..4e61cd7 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
@@ -29,7 +29,7 @@
     // do not introduce duplicates (bad for code size).
     Map<String, Selector> addedJsNames = new Map<String, Selector>();
 
-    void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) {
+    void addNoSuchMethodHandlers(String ignore, Set<Selector> selectors) {
       // Cache the object class and type.
       ClassElement objectClass = compiler.objectClass;
       DartType objectType = objectClass.computeType(compiler);
@@ -70,8 +70,8 @@
       }
 
       List<jsAst.Expression> argNames =
-          selector.getOrderedNamedArguments().map((SourceString name) =>
-              js.string(name.slowToString())).toList();
+          selector.getOrderedNamedArguments().map((String name) =>
+              js.string(name)).toList();
 
       String methodName = selector.invocationMirrorMemberName;
       String internalName = namer.invocationMirrorInternalName(selector);
diff --git a/sdk/lib/_internal/compiler/implementation/library_loader.dart b/sdk/lib/_internal/compiler/implementation/library_loader.dart
index 22a5493..478f36f 100644
--- a/sdk/lib/_internal/compiler/implementation/library_loader.dart
+++ b/sdk/lib/_internal/compiler/implementation/library_loader.dart
@@ -156,11 +156,11 @@
     // a positive list of elements to include, otherwise we create a negative
     // list of elements to exclude.
     bool show = false;
-    Set<SourceString> nameSet;
+    Set<String> nameSet;
     for (Combinator combinator in tag.combinators) {
       if (combinator.isShow) {
         show = true;
-        var set = new Set<SourceString>();
+        var set = new Set<String>();
         for (Identifier identifier in combinator.identifiers) {
           set.add(identifier.source);
         }
@@ -172,7 +172,7 @@
       }
     }
     if (nameSet == null) {
-      nameSet = new Set<SourceString>();
+      nameSet = new Set<String>();
     }
     for (Combinator combinator in tag.combinators) {
       if (combinator.isHide) {
@@ -195,7 +195,7 @@
  * A list of combinators represented as a list of element names to include.
  */
 class ShowFilter extends CombinatorFilter {
-  final Set<SourceString> includedNames;
+  final Set<String> includedNames;
 
   ShowFilter(this.includedNames);
 
@@ -206,7 +206,7 @@
  * A list of combinators represented as a list of element names to exclude.
  */
 class HideFilter extends CombinatorFilter {
-  final Set<SourceString> excludedNames;
+  final Set<String> excludedNames;
 
   HideFilter(this.excludedNames);
 
@@ -520,7 +520,7 @@
                      message: 'Exports not handled on $importedLibrary'));
     var combinatorFilter = new CombinatorFilter.fromTag(import);
     if (import != null && import.prefix != null) {
-      SourceString prefix = import.prefix.source;
+      String prefix = import.prefix.source;
       Element existingElement = importingLibrary.find(prefix);
       PrefixElement prefixElement;
       if (existingElement == null || !existingElement.isPrefix()) {
@@ -603,8 +603,8 @@
    * The export scope for [library] which is gradually computed by the work-list
    * computation in [LibraryDependencyHandler.computeExports].
    */
-  Map<SourceString, Element> exportScope =
-      new Map<SourceString, Element>();
+  Map<String, Element> exportScope =
+      new Map<String, Element>();
 
   /// Map from exported elements to the export directives that exported them.
   Map<Element, Link<Export>> exporters = new Map<Element, Link<Export>>();
@@ -696,7 +696,7 @@
    */
   Element addElementToExportScope(Compiler compiler, Element element,
                                   Link<Export> exports) {
-    SourceString name = element.name;
+    String name = element.name;
 
     void reportDuplicateExport(Element duplicate,
                                Link<Export> duplicateExports,
diff --git a/sdk/lib/_internal/compiler/implementation/mirror_renamer/mirror_renamer.dart b/sdk/lib/_internal/compiler/implementation/mirror_renamer/mirror_renamer.dart
index 5bd0db1..929479c 100644
--- a/sdk/lib/_internal/compiler/implementation/mirror_renamer/mirror_renamer.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirror_renamer/mirror_renamer.dart
@@ -6,7 +6,7 @@
 
 import '../dart2jslib.dart' show Script, Compiler;
 import '../tree/tree.dart';
-import '../scanner/scannerlib.dart' show SourceString, Token;
+import '../scanner/scannerlib.dart' show Token;
 import '../elements/elements.dart';
 import '../dart_backend/dart_backend.dart' show DartBackend,
                                                 PlaceholderCollector;
diff --git a/sdk/lib/_internal/compiler/implementation/mirror_renamer/renamer.dart b/sdk/lib/_internal/compiler/implementation/mirror_renamer/renamer.dart
index b1f8eaf..156a970 100644
--- a/sdk/lib/_internal/compiler/implementation/mirror_renamer/renamer.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirror_renamer/renamer.dart
@@ -10,7 +10,7 @@
   static const String MIRROR_HELPER_SYMBOLS_MAP_NAME = '_SYMBOLS';
 
   /// Maps mangled name to original name.
-  Map<String, SourceString> symbols = new Map<String, SourceString>();
+  Map<String, String> symbols = new Map<String, String>();
   /// Contains all occurrencs of MirrorSystem.getName() calls in the user code.
   List<Node> mirrorSystemGetNameNodes = <Node>[];
   /**
@@ -61,7 +61,7 @@
     }
 
     // Add toplevel map containing all renames of members.
-    symbols = new Map<String, SourceString>();
+    symbols = new Map<String, String>();
     for (Set<Identifier> s in placeholderCollector.memberPlaceholders.values) {
       // All members in a set have the same name so we only need to look at one.
       Identifier sampleNode = s.first;
@@ -74,7 +74,7 @@
     topLevelNodes.remove(mirrorHelperSymbolsMapNode);
 
     StringBuffer sb = new StringBuffer(
-        'const ${renames[symbolsMapIdentifier]} = const<String,SourceString>{');
+        'const ${renames[symbolsMapIdentifier]} = const<String,String>{');
     bool first = true;
     for (String mangledName in symbols.keys) {
       if (!first) {
@@ -83,10 +83,11 @@
         first = false;
       }
       sb.write("'$mangledName' : '");
-      symbols[mangledName].printOn(sb);
+      sb.write(symbols[mangledName]);
       sb.write("'");
     }
     sb.write('};');
+    sb.writeCharCode(0); // Terminate the string with '0', see [StringScanner].
     topLevelNodes.add(parse(sb.toString()));
 
     // Replace calls to Mirrorsystem.getName with calls to helper function.
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index 1aca15d..d7b26d6d 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -9,7 +9,7 @@
 import '../../compiler.dart' as api;
 import '../elements/elements.dart';
 import '../apiimpl.dart' as apiimpl;
-import '../scanner/scannerlib.dart' hide SourceString;
+import '../scanner/scannerlib.dart';
 import '../resolution/resolution.dart' show Scope;
 import '../dart2jslib.dart';
 import '../dart_types.dart';
@@ -289,7 +289,7 @@
    */
   Element get _beginElement => _element;
 
-  String get simpleName => _element.name.slowToString();
+  String get simpleName => _element.name;
 
   /**
    * Computes the first token for this declaration using the begin token of the
@@ -352,7 +352,7 @@
   void _appendCommentTokens(Token commentToken) {
     while (commentToken != null && commentToken.kind == COMMENT_TOKEN) {
       _metadata.add(new Dart2JsCommentInstanceMirror(
-          mirrors, commentToken.slowToString()));
+          mirrors, commentToken.value));
       commentToken = commentToken.next;
     }
   }
@@ -381,16 +381,16 @@
       // Lookup [: prefix.id :].
       String prefix = name.substring(0, index);
       String id = name.substring(index+1);
-      result = scope.lookup(new SourceString(prefix));
+      result = scope.lookup(prefix);
       if (result != null && result.isPrefix()) {
         PrefixElement prefix = result;
-        result = prefix.lookupLocalMember(new SourceString(id));
+        result = prefix.lookupLocalMember(id);
       } else {
         result = null;
       }
     } else {
       // Lookup [: id :].
-      result = scope.lookup(new SourceString(name));
+      result = scope.lookup(name);
     }
     if (result == null || result.isPrefix()) return null;
     return _convertElementToDeclarationMirror(mirrors, result);
@@ -1032,7 +1032,7 @@
     : super(system, type.element),
       this._type = type;
 
-  String get simpleName => _type.name.slowToString();
+  String get simpleName => _type.name;
 
   DeclarationMirror get owner => library;
 
@@ -1319,11 +1319,11 @@
 
   factory Dart2JsMethodMirror(Dart2JsContainerMirror objectMirror,
                               FunctionElement function) {
-    String realName = function.name.slowToString();
+    String realName = function.name;
     // TODO(ahe): This method should not be calling
     // Elements.operatorNameToIdentifier.
     String simpleName =
-        Elements.operatorNameToIdentifier(function.name).slowToString();
+        Elements.operatorNameToIdentifier(function.name);
     Dart2JsMethodKind kind;
     if (function.kind == ElementKind.GETTER) {
       kind = Dart2JsMethodKind.GETTER;
@@ -1605,7 +1605,7 @@
         var index = 0;
         ClassElement element = _constant.type.element;
         element.forEachInstanceField((_, Element field) {
-          String fieldName = field.name.slowToString();
+          String fieldName = field.name;
           _fieldMapCache.putIfAbsent(fieldName, () => _constant.fields[index]);
           index++;
         }, includeSuperAndInjectedMembers: true);
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
index aad7d8b..a5d6d52 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
@@ -11,7 +11,6 @@
     ConstructedConstant,
     ListConstant,
     MessageKind,
-    SourceString,
     StringConstant,
     TreeElements,
     TypeConstant,
@@ -146,17 +145,17 @@
               analyzer, mapping.currentElement.getLibrary(), named.expression,
               value, mapper.constantToNodeMap);
 
-      if (named.name.source == const SourceString('symbols')) {
+      if (named.name.source == 'symbols') {
         analyzer.cachedValues[value] =
             builder.convertToListOfStrings(
                 builder.convertConstantToUsageList(value, onlyStrings: true));
-      } else if (named.name.source == const SourceString('targets')) {
+      } else if (named.name.source == 'targets') {
         analyzer.cachedValues[value] =
             builder.resolveUsageList(builder.convertConstantToUsageList(value));
-      } else if (named.name.source == const SourceString('metaTargets')) {
+      } else if (named.name.source == 'metaTargets') {
         analyzer.cachedValues[value] =
             builder.resolveUsageList(builder.convertConstantToUsageList(value));
-      } else if (named.name.source == const SourceString('override')) {
+      } else if (named.name.source == 'override') {
         analyzer.cachedValues[value] =
             builder.resolveUsageList(builder.convertConstantToUsageList(value));
       }
@@ -331,14 +330,14 @@
   MirrorUsage buildUsage(ConstructedConstant constant) {
     Map<Element, Constant> fields = constant.fieldElements;
     VariableElement symbolsField = compiler.mirrorsUsedClass.lookupLocalMember(
-        const SourceString('symbols'));
+        'symbols');
     VariableElement targetsField = compiler.mirrorsUsedClass.lookupLocalMember(
-        const SourceString('targets'));
+        'targets');
     VariableElement metaTargetsField =
         compiler.mirrorsUsedClass.lookupLocalMember(
-            const SourceString('metaTargets'));
+            'metaTargets');
     VariableElement overrideField = compiler.mirrorsUsedClass.lookupLocalMember(
-        const SourceString('override'));
+        'override');
 
     return new MirrorUsage(
         cachedValues[fields[symbolsField]],
@@ -521,7 +520,7 @@
   /// Resolve [expression] in [enclosingLibrary]'s import scope.
   Element resolveExpression(String expression) {
     List<String> identifiers = expression.split('.');
-    Element element = enclosingLibrary.find(new SourceString(identifiers[0]));
+    Element element = enclosingLibrary.find(identifiers[0]);
     if (element == null) {
       compiler.reportHint(
           spannable, MessageKind.MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY,
@@ -537,7 +536,7 @@
   Element resolveLocalExpression(Element element, List<String> identifiers) {
     Element current = element;
     for (String identifier in identifiers) {
-      Element e = findLocalMemberIn(current, new SourceString(identifier));
+      Element e = findLocalMemberIn(current, identifier);
       if (e == null) {
         if (current.isLibrary()) {
           LibraryElement library = current;
@@ -559,7 +558,7 @@
 
   /// Helper method to lookup members in a [ScopeContainerElement]. If
   /// [element] is not a ScopeContainerElement, return null.
-  Element findLocalMemberIn(Element element, SourceString name) {
+  Element findLocalMemberIn(Element element, String name) {
     if (element is ScopeContainerElement) {
       ScopeContainerElement scope = element;
       if (element.isClass()) {
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index f16461b..a53f550 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -5,7 +5,7 @@
 library native;
 
 import 'dart:collection' show Queue;
-import 'dart2jslib.dart' hide SourceString;
+import 'dart2jslib.dart';
 import 'dart_types.dart';
 import 'elements/elements.dart';
 import 'js_backend/js_backend.dart';
@@ -150,15 +150,15 @@
     //
     //     class B extends foo.A {}
     //
-    // SourceString "A" has a potential subclass B.
+    // String "A" has a potential subclass B.
 
-    var potentialExtends = new Map<SourceString, Set<ClassElement>>();
+    var potentialExtends = new Map<String, Set<ClassElement>>();
 
     libraries.forEach((library) {
       library.implementation.forEachLocalMember((element) {
         if (element.isClass()) {
-          SourceString name = element.name;
-          SourceString extendsName = findExtendsNameOfClass(element);
+          String name = element.name;
+          String extendsName = findExtendsNameOfClass(element);
           if (extendsName != null) {
             Set<ClassElement> potentialSubclasses =
                 potentialExtends.putIfAbsent(
@@ -208,7 +208,7 @@
    * Returns the source string of the class named in the extends clause, or
    * `null` if there is no extends clause.
    */
-  SourceString findExtendsNameOfClass(ClassElement classElement) {
+  String findExtendsNameOfClass(ClassElement classElement) {
     //  "class B extends A ... {}"  --> "A"
     //  "class B extends foo.A ... {}"  --> "A"
     //  "class B<T> extends foo.A<T,T> with M1, M2 ... {}"  --> "A"
@@ -234,7 +234,7 @@
       //}
     }
 
-    SourceString scanForExtendsName(Token token) {
+    String scanForExtendsName(Token token) {
       if (token.stringValue == 'abstract') token = token.next;
       if (token.stringValue != 'class') return null;
       token = token.next;
@@ -287,9 +287,9 @@
       }
       return e;
     }
-    _annotationCreatesClass = find(const SourceString('Creates'));
-    _annotationReturnsClass = find(const SourceString('Returns'));
-    _annotationJsNameClass = find(const SourceString('JSName'));
+    _annotationCreatesClass = find('Creates');
+    _annotationReturnsClass = find('Returns');
+    _annotationJsNameClass = find('JSName');
   }
 
   /// Returns the JSName annotation string or `null` if no JSName annotation is
@@ -399,7 +399,7 @@
   /// defaulting to the Dart name.
   void setNativeName(Element element) {
     String name = findJsNameFromAnnotation(element);
-    if (name == null) name = element.name.slowToString();
+    if (name == null) name = element.name;
     element.setNative(name);
   }
 
@@ -507,28 +507,19 @@
           world, compiler.findHelper(name), compiler.globalDependencies);
     }
 
-    staticUse(const SourceString('dynamicFunction'));
-    staticUse(const SourceString('dynamicSetMetadata'));
-    staticUse(const SourceString('defineProperty'));
-    staticUse(const SourceString('toStringForNativeObject'));
-    staticUse(const SourceString('hashCodeForNativeObject'));
-    staticUse(const SourceString('convertDartClosureToJS'));
-    staticUse(const SourceString('defineNativeMethods'));
-    staticUse(const SourceString('defineNativeMethodsNonleaf'));
-    staticUse(const SourceString('defineNativeMethodsExtended'));
-    // TODO(9577): Registering `defineNativeMethodsFinish` seems redundant with
-    // respect to the registering in the backend. When the backend registering
-    // is removed as part of fixing Issue 9577, this can be the sole place
-    // registering this methods.
-    staticUse(const SourceString('defineNativeMethodsFinish'));
-
+    staticUse('dynamicFunction');
+    staticUse('dynamicSetMetadata');
+    staticUse('defineProperty');
+    staticUse('toStringForNativeObject');
+    staticUse('hashCodeForNativeObject');
+    staticUse('convertDartClosureToJS');
     addNativeExceptions();
   }
 
   addNativeExceptions() {
     enqueueUnusedClassesMatching((classElement) {
         // TODO(sra): Annotate exception classes in dart:html.
-        String name = classElement.name.slowToString();
+        String name = classElement.name;
         if (name.contains('Exception')) return true;
         if (name.contains('Error')) return true;
         return false;
@@ -852,7 +843,7 @@
     if (element.metadata.isEmpty) return;
 
     DartType lookup(String name) {
-      Element e = element.buildScope().lookup(new SourceString(name));
+      Element e = element.buildScope().lookup(name);
       if (e == null) return null;
       if (e is! ClassElement) return null;
       ClassElement cls = e;
@@ -1037,12 +1028,12 @@
   return token.next;
 }
 
-SourceString checkForNativeClass(ElementListener listener) {
-  SourceString nativeTagInfo;
+String checkForNativeClass(ElementListener listener) {
+  String nativeTagInfo;
   Node node = listener.nodes.head;
   if (node != null
       && node.asIdentifier() != null
-      && node.asIdentifier().source.stringValue == 'native') {
+      && node.asIdentifier().source == 'native') {
     nativeTagInfo = node.asIdentifier().token.next.value;
     listener.popNode();
   }
diff --git a/sdk/lib/_internal/compiler/implementation/patch_parser.dart b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
index fcd0be2..b528fa2 100644
--- a/sdk/lib/_internal/compiler/implementation/patch_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
@@ -162,7 +162,7 @@
     measure(() {
       // TODO(lrn): Possibly recursively handle 'part' directives in patch.
       leg.Script script = compilationUnit.script;
-      Token tokens = new StringScanner(script.text).tokenize();
+      Token tokens = new Scanner(script.file).tokenize();
       Function idGenerator = compiler.getNextFreeClassId;
       PatchListener patchListener =
           new PatchElementListener(compiler,
@@ -221,7 +221,7 @@
 
   PatchListener get patchListener => listener;
 
-  bool isPatch(Token token) => token.value == const SourceString('patch');
+  bool isPatch(Token token) => token.value == 'patch';
 
   /**
    * Parse top-level declarations, and allow "patch" in front of functions
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 4810fb6..69c82d4 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -6,10 +6,10 @@
 
 abstract class TreeElements {
   Element get currentElement;
-  Set<Node> get superUses;
+  Setlet<Node> get superUses;
 
   /// A set of additional dependencies.  See [registerDependency] below.
-  Set<Element> get otherDependencies;
+  Setlet<Element> get otherDependencies;
 
   Element operator[](Node node);
   Selector getSelector(Send send);
@@ -40,34 +40,36 @@
   /// For example, elements that are used by a backend.
   void registerDependency(Element element);
 
-  /// Returns [:true:] if [element] is potentially mutated anywhere in its
+  /// Returns a list of nodes that potentially mutate [element] anywhere in its
   /// scope.
-  bool isPotentiallyMutated(VariableElement element);
+  List<Node> getPotentialMutations(VariableElement element);
 
-  /// Returns [:true:] if [element] is potentially mutated in [node].
-  bool isPotentiallyMutatedIn(Node node, VariableElement element);
+  /// Returns a list of nodes that potentially mutate [element] in [node].
+  List<Node> getPotentialMutationsIn(Node node, VariableElement element);
 
-  /// Returns [:true:] if [element] is potentially mutated in a closure.
-  bool isPotentiallyMutatedInClosure(VariableElement element);
+  /// Returns a list of nodes that potentially mutate [element] in a closure.
+  List<Node> getPotentialMutationsInClosure(VariableElement element);
 
-  /// Returns [:true:] if [element] is accessed by a closure in [node].
-  bool isAccessedByClosureIn(Node node, VariableElement element);
+  /// Returns a list of nodes that access [element] within a closure in [node].
+  List<Node> getAccessesByClosureIn(Node node, VariableElement element);
 }
 
 class TreeElementMapping implements TreeElements {
   final Element currentElement;
   final Map<Spannable, Selector> selectors = new Map<Spannable, Selector>();
   final Map<Node, DartType> types = new Map<Node, DartType>();
-  final Set<Node> superUses = new Set<Node>();
-  final Set<Element> otherDependencies = new Set<Element>();
+  final Setlet<Node> superUses = new Setlet<Node>();
+  final Setlet<Element> otherDependencies = new Setlet<Element>();
   final Map<Node, Constant> constants = new Map<Node, Constant>();
-  final Set<VariableElement> potentiallyMutated = new Set<VariableElement>();
-  final Map<Node, Set<VariableElement>> potentiallyMutatedIn =
-      new Map<Node, Set<VariableElement>>();
-  final Set<VariableElement> potentiallyMutatedInClosure =
-      new Set<VariableElement>();
-  final Map<Node, Set<VariableElement>> accessedByClosureIn =
-      new Map<Node, Set<VariableElement>>();
+  final Map<VariableElement, List<Node>> potentiallyMutated =
+      new Map<VariableElement, List<Node>>();
+  final Map<Node, Map<VariableElement, List<Node>>> potentiallyMutatedIn =
+      new Map<Node,  Map<VariableElement, List<Node>>>();
+  final Map<VariableElement, List<Node>> potentiallyMutatedInClosure =
+      new Map<VariableElement, List<Node>>();
+  final Map<Node, Map<VariableElement, List<Node>>> accessedByClosureIn =
+      new Map<Node, Map<VariableElement, List<Node>>>();
+
   final int hashCode = ++hashCodeCounter;
   static int hashCodeCounter = 0;
 
@@ -178,40 +180,58 @@
     otherDependencies.add(element.implementation);
   }
 
-  bool isPotentiallyMutated(VariableElement element) {
-    return potentiallyMutated.contains(element);
+  List<Node> getPotentialMutations(VariableElement element) {
+    List<Node> mutations = potentiallyMutated[element];
+    if (mutations == null) return const <Node>[];
+    return mutations;
   }
 
-  void setPotentiallyMutated(VariableElement element) {
-    potentiallyMutated.add(element);
+  void setPotentiallyMutated(VariableElement element, Node mutationNode) {
+    potentiallyMutated.putIfAbsent(element, () => <Node>[]).add(mutationNode);
   }
 
-  bool isPotentiallyMutatedIn(Node node, VariableElement element) {
-    Set<Element> mutatedIn = potentiallyMutatedIn[node];
-    return mutatedIn != null && mutatedIn.contains(element);
+  List<Node> getPotentialMutationsIn(Node node, VariableElement element) {
+    Map<VariableElement, List<Node>> mutationsIn = potentiallyMutatedIn[node];
+    if (mutationsIn == null) return const <Node>[];
+    List<Node> mutations = mutationsIn[element];
+    if (mutations == null) return const <Node>[];
+    return mutations;
   }
 
-  void setPotentiallyMutatedIn(Node node, VariableElement element) {
-    potentiallyMutatedIn.putIfAbsent(
-        node, () => new Set<VariableElement>()).add(element);
+  void registerPotentiallyMutatedIn(Node contextNode, VariableElement element,
+                                    Node mutationNode) {
+    Map<VariableElement, List<Node>> mutationMap =
+      potentiallyMutatedIn.putIfAbsent(contextNode,
+          () => new Map<VariableElement, List<Node>>());
+    mutationMap.putIfAbsent(element, () => <Node>[]).add(mutationNode);
   }
 
-  bool isPotentiallyMutatedInClosure(VariableElement element) {
-    return potentiallyMutatedInClosure.contains(element);
+  List<Node> getPotentialMutationsInClosure(VariableElement element) {
+    List<Node> mutations = potentiallyMutatedInClosure[element];
+    if (mutations == null) return const <Node>[];
+    return mutations;
   }
 
-  void setPotentiallyMutatedInClosure(VariableElement element) {
-    potentiallyMutatedInClosure.add(element);
+  void registerPotentiallyMutatedInClosure(VariableElement element,
+                                           Node mutationNode) {
+    potentiallyMutatedInClosure.putIfAbsent(
+        element, () => <Node>[]).add(mutationNode);
   }
 
-  bool isAccessedByClosureIn(Node node, VariableElement element) {
-    Set<Element> accessedIn = accessedByClosureIn[node];
-    return accessedIn != null && accessedIn.contains(element);
+  List<Node> getAccessesByClosureIn(Node node, VariableElement element) {
+    Map<VariableElement, List<Node>> accessesIn = accessedByClosureIn[node];
+    if (accessesIn == null) return const <Node>[];
+    List<Node> accesses = accessesIn[element];
+    if (accesses == null) return const <Node>[];
+    return accesses;
   }
 
-  void setAccessedByClosureIn(Node node, VariableElement element) {
-    accessedByClosureIn.putIfAbsent(
-        node, () => new Set<VariableElement>()).add(element);
+  void setAccessedByClosureIn(Node contextNode, VariableElement element,
+                              Node accessNode) {
+    Map<VariableElement, List<Node>> accessMap =
+        accessedByClosureIn.putIfAbsent(contextNode,
+          () => new Map<VariableElement, List<Node>>());
+    accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode);
   }
 
   String toString() => 'TreeElementMapping($currentElement)';
@@ -261,11 +281,11 @@
     });
   }
 
-  String constructorNameForDiagnostics(SourceString className,
-                                       SourceString constructorName) {
-    String classNameString = className.slowToString();
-    String constructorNameString = constructorName.slowToString();
-    return (constructorName == const SourceString(''))
+  String constructorNameForDiagnostics(String className,
+                                       String constructorName) {
+    String classNameString = className;
+    String constructorNameString = constructorName;
+    return (constructorName == '')
         ? classNameString
         : "$classNameString.$constructorNameString";
    }
@@ -274,7 +294,7 @@
                                      Node node,
                                      FunctionElement constructor,
                                      FunctionElement redirection) {
-    Set<FunctionElement> seen = new Set<FunctionElement>();
+    Setlet<FunctionElement> seen = new Setlet<FunctionElement>();
     seen.add(constructor);
     while (redirection != null) {
       if (seen.contains(redirection)) {
@@ -583,7 +603,7 @@
     return result;
   }
 
-  void resolveRedirectionChain(FunctionElement constructor, Node node) {
+  void resolveRedirectionChain(FunctionElement constructor, Spannable node) {
     FunctionElementX current = constructor;
     List<Element> seen = new List<Element>();
     // Follow the chain of redirections and check for cycles.
@@ -793,7 +813,7 @@
                            MixinApplicationElement mixinApplication,
                            ClassElement mixin) {
     if (resolutionTree == null) return;
-    Set<Node> superUses = resolutionTree.superUses;
+    Setlet<Node> superUses = resolutionTree.superUses;
     if (superUses.isEmpty) return;
     compiler.reportError(mixinApplication,
                          MessageKind.ILLEGAL_MIXIN_WITH_SUPER,
@@ -908,7 +928,7 @@
   void checkUserDefinableOperator(Element member) {
     FunctionElement function = member.asFunctionElement();
     if (function == null) return;
-    String value = member.name.stringValue;
+    String value = member.name;
     if (value == null) return;
     if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return;
 
@@ -945,11 +965,11 @@
     if (operatorEquals.isAbstract(compiler)) return;
     ClassElement cls = operatorEquals.getEnclosingClass();
     Element hashCodeImplementation =
-        cls.lookupLocalMember(const SourceString('hashCode'));
+        cls.lookupLocalMember('hashCode');
     if (hashCodeImplementation != null) return;
     compiler.reportHint(
         operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE,
-        {'class': cls.name.slowToString()});
+        {'class': cls.name});
   }
 
   void checkArity(FunctionElement function,
@@ -1103,10 +1123,10 @@
        parameterTypes.addLast(parameter.computeType(compiler));
     }
     var optionalParameterTypes = const Link<DartType>();
-    var namedParameters = const Link<SourceString>();
+    var namedParameters = const Link<String>();
     var namedParameterTypes = const Link<DartType>();
     if (signature.optionalParametersAreNamed) {
-      var namedParametersBuilder = new LinkBuilder<SourceString>();
+      var namedParametersBuilder = new LinkBuilder<String>();
       var namedParameterTypesBuilder = new LinkBuilder<DartType>();
       for (Element parameter in signature.orderedOptionalParameters) {
         namedParametersBuilder.addLast(parameter.name);
@@ -1151,7 +1171,7 @@
     }));
   }
 
-  error(Node node, MessageKind kind, [arguments = const {}]) {
+  error(Spannable node, MessageKind kind, [arguments = const {}]) {
     // TODO(ahe): Make non-fatal.
     compiler.reportFatalError(node, kind, arguments);
   }
@@ -1210,7 +1230,7 @@
   void checkForDuplicateInitializers(Element field, Node init) {
     // [field] can be null if it could not be resolved.
     if (field == null) return;
-    SourceString name = field.name;
+    String name = field.name;
     if (initialized.containsKey(field)) {
       reportDuplicateInitializerError(field, init, initialized[field]);
     } else if (field.modifiers.isFinal()) {
@@ -1225,7 +1245,7 @@
   void resolveFieldInitializer(FunctionElement constructor, SendSet init) {
     // init is of the form [this.]field = value.
     final Node selector = init.selector;
-    final SourceString name = selector.asIdentifier().source;
+    final String name = selector.asIdentifier().source;
     // Lookup target field.
     Element target;
     if (isFieldInitializer(init)) {
@@ -1283,7 +1303,7 @@
         lookupTarget.lookupConstructor(constructorSelector);
 
     final bool isImplicitSuperCall = false;
-    final SourceString className = lookupTarget.name;
+    final String className = lookupTarget.name;
     verifyThatConstructorMatchesCall(constructor,
                                      calledConstructor,
                                      selector,
@@ -1305,7 +1325,7 @@
     if (classElement != visitor.compiler.objectClass) {
       assert(superClass != null);
       assert(superClass.resolutionState == STATE_DONE);
-      SourceString constructorName = const SourceString('');
+      String constructorName = '';
       Selector callToMatch = new Selector.call(
           constructorName,
           classElement.getLibrary(),
@@ -1320,7 +1340,7 @@
       Element calledConstructor = lookupTarget.lookupConstructor(
           constructorSelector);
 
-      final SourceString className = lookupTarget.name;
+      final String className = lookupTarget.name;
       final bool isImplicitSuperCall = true;
       verifyThatConstructorMatchesCall(constructor,
                                        calledConstructor,
@@ -1340,7 +1360,7 @@
       Selector call,
       bool isImplicitSuperCall,
       Node diagnosticNode,
-      SourceString className,
+      String className,
       Selector constructorSelector) {
     if (lookedupConstructor == null
         || !lookedupConstructor.isGenerativeConstructor()) {
@@ -1623,7 +1643,7 @@
         return null;
       }
     } else {
-      String stringValue = typeName.source.stringValue;
+      String stringValue = typeName.source;
       if (identical(stringValue, 'void')) {
         return compiler.types.voidType.element;
       } else if (identical(stringValue, 'dynamic')) {
@@ -1874,7 +1894,7 @@
     return element;
   }
 
-  void reportDuplicateDefinition(/*Node|SourceString*/ name,
+  void reportDuplicateDefinition(/*Node|String*/ name,
                                  Spannable definition,
                                  Spannable existing) {
     compiler.reportError(
@@ -1975,7 +1995,7 @@
 
   ResolutionEnqueuer get world => compiler.enqueuer.resolution;
 
-  Element reportLookupErrorIfAny(Element result, Node node, SourceString name) {
+  Element reportLookupErrorIfAny(Element result, Node node, String name) {
     if (!Elements.isUnresolved(result)) {
       if (!inInstanceContext && result.isInstanceMember()) {
         compiler.reportError(
@@ -2036,7 +2056,7 @@
   }
 
   ErroneousElement warnAndCreateErroneousElement(Node node,
-                                                 SourceString name,
+                                                 String name,
                                                  DualKind kind,
                                                  [Map arguments = const {}]) {
     ResolutionWarning warning = new ResolutionWarning(
@@ -2058,9 +2078,9 @@
       }
       return null;
     } else {
-      SourceString name = node.source;
+      String name = node.source;
       Element element = lookupInScope(compiler, node, scope, name);
-      if (Elements.isUnresolved(element) && name.slowToString() == 'dynamic') {
+      if (Elements.isUnresolved(element) && name == 'dynamic') {
         element = compiler.dynamicClass;
       }
       element = reportLookupErrorIfAny(element, node, node.source);
@@ -2103,7 +2123,7 @@
 
   Selector getRedirectingThisOrSuperConstructorSelector(Send node) {
     if (isNamedConstructor(node)) {
-      SourceString constructorName = node.selector.asIdentifier().source;
+      String constructorName = node.selector.asIdentifier().source;
       return new Selector.callConstructor(
           constructorName,
           enclosingElement.getLibrary());
@@ -2244,9 +2264,9 @@
 
   visitFunctionExpression(FunctionExpression node) {
     visit(node.returnType);
-    SourceString name;
+    String name;
     if (node.name == null) {
-      name = const SourceString("");
+      name = "";
     } else {
       name = node.name.asIdentifier().source;
     }
@@ -2280,7 +2300,7 @@
   }
 
   static bool isLogicalOperator(Identifier op) {
-    String str = op.source.stringValue;
+    String str = op.source;
     return (identical(str, '&&') || str == '||' || str == '!');
   }
 
@@ -2313,14 +2333,14 @@
     allowedCategory = oldCategory;
 
     Element target;
-    SourceString name = node.selector.asIdentifier().source;
-    if (identical(name.stringValue, 'this')) {
+    String name = node.selector.asIdentifier().source;
+    if (identical(name, 'this')) {
       // TODO(ahe): Why is this using GENERIC?
       error(node.selector, MessageKind.GENERIC,
             {'text': "expected an identifier"});
     } else if (node.isSuperCall) {
       if (node.isOperator) {
-        if (isUserDefinableOperator(name.stringValue)) {
+        if (isUserDefinableOperator(name)) {
           name = selector.name;
         } else {
           error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name});
@@ -2409,8 +2429,8 @@
     }
 
     if (node.isOperator) {
-      SourceString source = node.selector.asOperator().source;
-      String string = source.stringValue;
+      String source = node.selector.asOperator().source;
+      String string = source;
       if (identical(string, '!') ||
           identical(string, '&&') || identical(string, '||') ||
           identical(string, 'is') || identical(string, 'as') ||
@@ -2418,8 +2438,8 @@
           identical(string, '>>>')) {
         return null;
       }
-      SourceString op = source;
-      if (!isUserDefinableOperator(source.stringValue)) {
+      String op = source;
+      if (!isUserDefinableOperator(source)) {
         op = Elements.mapToUserOperatorOrNull(source);
       }
       if (op == null) {
@@ -2442,7 +2462,7 @@
 
     // Compute the arity and the list of named arguments.
     int arity = 0;
-    List<SourceString> named = <SourceString>[];
+    List<String> named = <String>[];
     for (Link<Node> link = node.argumentsNode.nodes;
         !link.isEmpty;
         link = link.tail) {
@@ -2476,13 +2496,13 @@
     if (list == null) return;
     bool oldSendIsMemberAccess = sendIsMemberAccess;
     sendIsMemberAccess = false;
-    Map<SourceString, Node> seenNamedArguments = new Map<SourceString, Node>();
+    Map<String, Node> seenNamedArguments = new Map<String, Node>();
     for (Link<Node> link = list.nodes; !link.isEmpty; link = link.tail) {
       Expression argument = link.head;
       visit(argument);
       NamedArgument namedArgument = argument.asNamedArgument();
       if (namedArgument != null) {
-        SourceString source = namedArgument.name.source;
+        String source = namedArgument.name.source;
         if (seenNamedArguments.containsKey(source)) {
           reportDuplicateDefinition(
               source,
@@ -2549,7 +2569,7 @@
       if (isPotentiallyMutableTarget(target)) {
         if (enclosingElement != target.enclosingElement) {
           for (Node scope in promotionScope) {
-            mapping.setAccessedByClosureIn(scope, target);
+            mapping.setAccessedByClosureIn(scope, target, node);
           }
         }
       }
@@ -2557,7 +2577,7 @@
 
     bool resolvedArguments = false;
     if (node.isOperator) {
-      String operatorString = node.selector.asOperator().source.stringValue;
+      String operatorString = node.selector.asOperator().source;
       if (identical(operatorString, 'is')) {
         // TODO(johnniwinther): Use seen type tests to avoid registration of
         // mutation/access to unpromoted variables.
@@ -2609,7 +2629,7 @@
 
       if (target != null &&
           target.isForeign(compiler) &&
-          selector.name == const SourceString('JS')) {
+          selector.name == 'JS') {
         world.registerJsCall(node, this);
       }
     }
@@ -2635,7 +2655,7 @@
   /// Callback for native enqueuer to parse a type.  Returns [:null:] on error.
   DartType resolveTypeFromString(Node node, String typeName) {
     Element element = lookupInScope(compiler, node,
-                                    scope, new SourceString(typeName));
+                                    scope, typeName);
     if (element == null) return null;
     if (element is! ClassElement) return null;
     ClassElement cls = element;
@@ -2650,8 +2670,8 @@
     sendIsMemberAccess = oldSendIsMemberAccess;
     Element setter = target;
     Element getter = target;
-    SourceString operatorName = node.assignmentOperator.source;
-    String source = operatorName.stringValue;
+    String operatorName = node.assignmentOperator.source;
+    String source = operatorName;
     bool isComplex = !identical(source, '=');
     if (!Elements.isUnresolved(target)) {
       if (target.isAbstractField()) {
@@ -2680,12 +2700,12 @@
         compiler.backend.registerThrowNoSuchMethod(mapping);
       }
       if (isPotentiallyMutableTarget(target)) {
-        mapping.setPotentiallyMutated(target);
+        mapping.setPotentiallyMutated(target, node);
         if (enclosingElement != target.enclosingElement) {
-          mapping.setPotentiallyMutatedInClosure(target);
+          mapping.registerPotentiallyMutatedInClosure(target, node);
         }
         for (Node scope in promotionScope) {
-          mapping.setPotentiallyMutatedIn(scope, target);
+          mapping.registerPotentiallyMutatedIn(scope, target, node);
         }
       }
     }
@@ -2720,16 +2740,16 @@
 
       // Make sure we include the + and - operators if we are using
       // the ++ and -- ones.  Also, if op= form is used, include op itself.
-      void registerBinaryOperator(SourceString name) {
+      void registerBinaryOperator(String name) {
         Selector binop = new Selector.binaryOperator(name);
         world.registerDynamicInvocation(binop);
         mapping.setOperatorSelectorInComplexSendSet(node, binop);
       }
       if (identical(source, '++')) {
-        registerBinaryOperator(const SourceString('+'));
+        registerBinaryOperator('+');
         world.registerInstantiatedClass(compiler.intClass, mapping);
       } else if (identical(source, '--')) {
-        registerBinaryOperator(const SourceString('-'));
+        registerBinaryOperator('-');
         world.registerInstantiatedClass(compiler.intClass, mapping);
       } else if (source.endsWith('=')) {
         registerBinaryOperator(Elements.mapToUserOperator(operatorName));
@@ -2915,7 +2935,7 @@
       for (Link<Node> nodes = modifiers.nodes.nodes;
            !nodes.isEmpty;
            nodes = nodes.tail) {
-        if (modifier == nodes.head.asIdentifier().source.stringValue) {
+        if (modifier == nodes.head.asIdentifier().source) {
           modifierNode = nodes.head;
           break;
         }
@@ -3130,7 +3150,7 @@
   }
 
   visitStringInterpolationPart(StringInterpolationPart node) {
-    registerImplicitInvocation(const SourceString('toString'), 0);
+    registerImplicitInvocation('toString', 0);
     node.visitChildren(this);
   }
 
@@ -3144,7 +3164,7 @@
       }
       target.isBreakTarget = true;
     } else {
-      String labelName = node.target.source.slowToString();
+      String labelName = node.target.source;
       LabelElement label = statementScope.lookupLabel(labelName);
       if (label == null) {
         error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
@@ -3177,7 +3197,7 @@
       }
       target.isContinueTarget = true;
     } else {
-      String labelName = node.target.source.slowToString();
+      String labelName = node.target.source;
       LabelElement label = statementScope.lookupLabel(labelName);
       if (label == null) {
         error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
@@ -3193,7 +3213,7 @@
     mapping[node] = target;
   }
 
-  registerImplicitInvocation(SourceString name, int arity) {
+  registerImplicitInvocation(String name, int arity) {
     Selector selector = new Selector.call(name, null, arity);
     world.registerDynamicInvocation(selector);
   }
@@ -3271,7 +3291,7 @@
     TargetElement targetElement = getOrCreateTargetElement(body);
     Map<String, LabelElement> labelElements = <String, LabelElement>{};
     for (Label label in node.labels) {
-      String labelName = label.slowToString();
+      String labelName = label.labelName;
       if (labelElements.containsKey(labelName)) continue;
       LabelElement element = targetElement.addLabel(label, labelName);
       labelElements[labelName] = element;
@@ -3364,7 +3384,7 @@
           continue;
         }
         Label label = labelOrCase;
-        String labelName = label.slowToString();
+        String labelName = label.labelName;
 
         LabelElement existingElement = continueLabels[labelName];
         if (existingElement != null) {
@@ -3528,13 +3548,13 @@
   void resolveTypeVariableBounds(NodeList node) {
     if (node == null) return;
 
-    var nameSet = new Set<SourceString>();
+    var nameSet = new Setlet<String>();
     // Resolve the bounds of type variables.
     Link<DartType> typeLink = element.typeVariables;
     Link<Node> nodeLink = node.nodes;
     while (!nodeLink.isEmpty) {
       TypeVariableType typeVariable = typeLink.head;
-      SourceString typeName = typeVariable.name;
+      String typeName = typeVariable.name;
       TypeVariable typeNode = nodeLink.head;
       if (nameSet.contains(typeName)) {
         error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME,
@@ -3605,8 +3625,7 @@
     element.alias = compiler.computeFunctionType(element, signature);
 
     void checkCyclicReference() {
-      var visitor = new TypedefCyclicVisitor(compiler, element);
-      type.accept(visitor, null);
+      element.checkCyclicReference(compiler);
     }
     addPostProcessAction(element, checkCyclicReference);
   }
@@ -3616,13 +3635,9 @@
 // annotations in typedef alias are stored in a [TreeElements] mapping.
 class TypedefCyclicVisitor extends DartTypeVisitor {
   final Compiler compiler;
-  final TypedefElement element;
+  final TypedefElementX element;
   bool hasCyclicReference = false;
 
-  /// Counter for how many bounds the visitor currently has on the call-stack.
-  /// Used to detect when to report [Messagekind.CYCLIC_TYPEDEF_TYPEVAR].
-  int seenBoundsCount = 0;
-
   Link<TypedefElement> seenTypedefs = const Link<TypedefElement>();
 
   int seenTypedefsCount = 0;
@@ -3643,9 +3658,7 @@
         // Only report an error on the checked typedef to avoid generating
         // multiple errors for the same cyclicity.
         hasCyclicReference = true;
-        if (seenBoundsCount > 0) {
-          compiler.reportError(element, MessageKind.CYCLIC_TYPEDEF_TYPEVAR);
-        } else if (seenTypedefsCount == 1) {
+        if (seenTypedefsCount == 1) {
           // Direct cyclicity.
           compiler.reportError(element,
               MessageKind.CYCLIC_TYPEDEF,
@@ -3667,6 +3680,13 @@
             }
           }
         }
+        ErroneousElementX erroneousElement = new ErroneousElementX(
+              MessageKind.CYCLIC_TYPEDEF,
+              {'typedefName': element.name},
+              element.name, element);
+        element.alias =
+            new MalformedType(erroneousElement, typedefElement.alias);
+        element.hasBeenCheckedForCycles = true;
       }
     } else {
       seenTypedefs = seenTypedefs.prepend(typedefElement);
@@ -3694,9 +3714,7 @@
       return;
     }
     seenTypeVariables = seenTypeVariables.prepend(typeVariableElement);
-    seenBoundsCount++;
     typeVariableElement.bound.accept(this, null);
-    seenBoundsCount--;
     seenTypeVariables = seenTypeVariables.tail;
   }
 }
@@ -3774,15 +3792,15 @@
 
     if (!element.hasConstructor) {
       Element superMember =
-          element.superclass.localLookup(const SourceString(''));
+          element.superclass.localLookup('');
       if (superMember == null || !superMember.isGenerativeConstructor()) {
         DualKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR;
-        Map arguments = {'constructorName': const SourceString('')};
+        Map arguments = {'constructorName': ''};
         // TODO(ahe): Why is this a compile-time error? Or if it is an error,
         // why do we bother to registerThrowNoSuchMethod below?
         compiler.reportError(node, kind.error, arguments);
         superMember = new ErroneousElementX(
-            kind.error, arguments, const SourceString(''), element);
+            kind.error, arguments, '', element);
         compiler.backend.registerThrowNoSuchMethod(mapping);
       }
       FunctionElement constructor =
@@ -3835,10 +3853,10 @@
   }
 
   DartType applyMixin(DartType supertype, DartType mixinType, Node node) {
-    String superName = supertype.name.slowToString();
-    String mixinName = mixinType.name.slowToString();
+    String superName = supertype.name;
+    String mixinName = mixinType.name;
     ClassElement mixinApplication = new MixinApplicationElementX(
-        new SourceString("${superName}+${mixinName}"),
+        "${superName}+${mixinName}",
         element.getCompilationUnit(),
         compiler.getNextFreeClassId(),
         node,
@@ -3850,7 +3868,7 @@
   }
 
   bool isDefaultConstructor(FunctionElement constructor) {
-    return constructor.name == const SourceString('') &&
+    return constructor.name == '' &&
         constructor.computeSignature(compiler).parameterCount == 0;
   }
 
@@ -4169,7 +4187,7 @@
   }
 }
 
-class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
+class VariableDefinitionsVisitor extends CommonResolverVisitor<String> {
   VariableDefinitions definitions;
   ResolverVisitor resolver;
   ElementKind kind;
@@ -4182,10 +4200,10 @@
         definitions, ElementKind.VARIABLE_LIST, resolver.enclosingElement);
   }
 
-  SourceString visitSendSet(SendSet node) {
+  String visitSendSet(SendSet node) {
     assert(node.arguments.tail.isEmpty); // Sanity check
     Identifier identifier = node.selector;
-    SourceString name = identifier.source;
+    String name = identifier.source;
     VariableDefinitionScope scope =
         new VariableDefinitionScope(resolver.scope, name);
     resolver.visitIn(node.arguments.head, scope);
@@ -4196,7 +4214,7 @@
     return name;
   }
 
-  SourceString visitIdentifier(Identifier node) {
+  String visitIdentifier(Identifier node) {
     // The variable is initialized to null.
     resolver.world.registerInstantiatedClass(compiler.nullClass,
                                              resolver.mapping);
@@ -4212,7 +4230,7 @@
 
   visitNodeList(NodeList node) {
     for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
-      SourceString name = visit(link.head);
+      String name = visit(link.head);
       VariableElement element =
           new VariableElementX(name, variables, kind, link.head);
       resolver.defineElement(link.head, element);
@@ -4289,10 +4307,10 @@
   }
 
   void validateName(Identifier node) {
-    SourceString name = node.source;
+    String name = node.source;
     if (isOptionalParameter &&
         optionalParametersAreNamed &&
-        node.source.isPrivate()) {
+        isPrivateName(node.source)) {
       compiler.reportError(node, MessageKind.PRIVATE_NAMED_PARAMETER);
     }
   }
@@ -4307,7 +4325,7 @@
         ElementKind.PARAMETER, node);
   }
 
-  SourceString getParameterName(Send node) {
+  String getParameterName(Send node) {
     var identifier = node.selector.asIdentifier();
     if (identifier != null) {
       // Normal parameter: [:Type name:].
@@ -4338,7 +4356,7 @@
                           ElementKind.GENERATIVE_CONSTRUCTOR)) {
       error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED);
     } else {
-      SourceString name = getParameterName(node);
+      String name = getParameterName(node);
       Element fieldElement = currentClass.lookupLocalMember(name);
       if (fieldElement == null ||
           !identical(fieldElement.kind, ElementKind.FIELD)) {
@@ -4366,7 +4384,7 @@
           node.selector.asIdentifier() :
           node.selector.asFunctionExpression().name.asIdentifier();
       validateName(identifier);
-      SourceString source = identifier.source;
+      String source = identifier.source;
       element = new VariableElementX(source, variables,
           ElementKind.PARAMETER, node);
     }
@@ -4502,7 +4520,7 @@
   }
 
   failOrReturnErroneousElement(Element enclosing, Node diagnosticNode,
-                               SourceString targetName, DualKind kind,
+                               String targetName, DualKind kind,
                                Map arguments) {
     if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) {
       compiler.backend.registerThrowNoSuchMethod(resolver.mapping);
@@ -4521,8 +4539,8 @@
     }
   }
 
-  Selector createConstructorSelector(SourceString constructorName) {
-    return constructorName == const SourceString('')
+  Selector createConstructorSelector(String constructorName) {
+    return constructorName == ''
         ? new Selector.callDefaultConstructor(
             resolver.enclosingElement.getLibrary())
         : new Selector.callConstructor(
@@ -4533,7 +4551,7 @@
   // TODO(ngeoffray): method named lookup should not report errors.
   FunctionElement lookupConstructor(ClassElement cls,
                                     Node diagnosticNode,
-                                    SourceString constructorName) {
+                                    String constructorName) {
     cls.ensureResolved(compiler);
     Selector selector = createConstructorSelector(constructorName);
     Element result = cls.lookupConstructor(selector);
@@ -4545,7 +4563,7 @@
       return failOrReturnErroneousElement(
           cls,
           diagnosticNode,
-          new SourceString(fullConstructorName),
+          fullConstructorName,
           MessageKind.CANNOT_FIND_CONSTRUCTOR,
           {'constructorName': fullConstructorName});
     } else if (inConstContext && !result.modifiers.isConst()) {
@@ -4573,7 +4591,7 @@
         ClassElement cls = e;
         cls.ensureResolved(compiler);
         // The unnamed constructor may not exist, so [e] may become unresolved.
-        e = lookupConstructor(cls, diagnosticNode, const SourceString(''));
+        e = lookupConstructor(cls, diagnosticNode, '');
       } else {
         e = failOrReturnErroneousElement(
               e, diagnosticNode, e.name, MessageKind.NOT_A_TYPE,
@@ -4628,7 +4646,7 @@
   }
 
   Element visitIdentifier(Identifier node) {
-    SourceString name = node.source;
+    String name = node.source;
     Element e = resolver.reportLookupErrorIfAny(
         lookupInScope(compiler, node, resolver.scope, name), node, name);
     // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
@@ -4661,6 +4679,6 @@
 
 /// Looks up [name] in [scope] and unwraps the result.
 Element lookupInScope(Compiler compiler, Node node,
-                      Scope scope, SourceString name) {
+                      Scope scope, String name) {
   return Elements.unwrap(scope.lookup(name), compiler, node);
 }
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/scope.dart b/sdk/lib/_internal/compiler/implementation/resolution/scope.dart
index 81eadae..e31e9ff 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/scope.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/scope.dart
@@ -14,7 +14,7 @@
   /**
    * Looks up the [Element] for [name] in this scope.
    */
-  Element lookup(SourceString name);
+  Element lookup(String name);
 
   static Scope buildEnclosingScope(Element element) {
     return element.enclosingElement != null
@@ -27,13 +27,13 @@
 
   NestedScope(this.parent);
 
-  Element lookup(SourceString name) {
+  Element lookup(String name) {
     Element result = localLookup(name);
     if (result != null) return result;
     return parent.lookup(name);
   }
 
-  Element localLookup(SourceString name);
+  Element localLookup(String name);
 
   static Scope buildEnclosingScope(Element element) {
     return element.enclosingElement != null
@@ -42,12 +42,12 @@
 }
 
 class VariableDefinitionScope extends NestedScope {
-  final SourceString variableName;
+  final String variableName;
   bool variableReferencedInInitializer = false;
 
   VariableDefinitionScope(Scope parent, this.variableName) : super(parent);
 
-  Element localLookup(SourceString name) {
+  Element localLookup(String name) {
     if (name == variableName) {
       variableReferencedInInitializer = true;
     }
@@ -78,7 +78,7 @@
     throw "Cannot add element to TypeDeclarationScope";
   }
 
-  Element lookupTypeVariable(SourceString name) {
+  Element lookupTypeVariable(String name) {
     Link<DartType> typeVariableLink = element.typeVariables;
     while (!typeVariableLink.isEmpty) {
       TypeVariableType typeVariable = typeVariableLink.head;
@@ -90,18 +90,18 @@
     return null;
   }
 
-  Element localLookup(SourceString name) => lookupTypeVariable(name);
+  Element localLookup(String name) => lookupTypeVariable(name);
 
   String toString() =>
       'TypeDeclarationScope($element)';
 }
 
 abstract class MutableScope extends NestedScope {
-  final Map<SourceString, Element> elements;
+  final Map<String, Element> elements;
 
   MutableScope(Scope parent)
       : super(parent),
-        this.elements = new Map<SourceString, Element>() {
+        this.elements = new Map<String, Element>() {
     assert(parent != null);
   }
 
@@ -113,7 +113,7 @@
     return newElement;
   }
 
-  Element localLookup(SourceString name) => elements[name];
+  Element localLookup(String name) => elements[name];
 }
 
 class MethodScope extends MutableScope {
@@ -144,13 +144,13 @@
     assert(parent != null);
   }
 
-  Element localLookup(SourceString name) {
+  Element localLookup(String name) {
     Element result = element.lookupLocalMember(name);
     if (result != null) return result;
     return super.localLookup(name);
   }
 
-  Element lookup(SourceString name) {
+  Element lookup(String name) {
     Element result = localLookup(name);
     if (result != null) return result;
     result = parent.lookup(name);
@@ -170,8 +170,8 @@
 
   LibraryScope(LibraryElement this.library);
 
-  Element localLookup(SourceString name) => library.find(name);
-  Element lookup(SourceString name) => localLookup(name);
+  Element localLookup(String name) => library.find(name);
+  Element lookup(String name) => localLookup(name);
 
   Element add(Element newElement) {
     throw "Cannot add an element to a library scope";
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
index 01f8e9e..5eb9129 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
@@ -2,35 +2,49 @@
 // 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 scanner_implementation;
+part of scanner;
 
-abstract
-class ArrayBasedScanner<S extends SourceString> extends AbstractScanner<S> {
-  int get charOffset => byteOffset + extraCharOffset;
-  final Token tokens;
-  Token tail;
-  int tokenStart;
-  int byteOffset;
-  final bool includeComments;
+abstract class ArrayBasedScanner extends AbstractScanner {
+  ArrayBasedScanner(SourceFile file, bool includeComments)
+      : super(file, includeComments);
 
-  /** Since the input is UTF8, some characters are represented by more
-   * than one byte. [extraCharOffset] tracks the difference. */
-  int extraCharOffset;
+  /**
+   * The stack of open groups, e.g [: { ... ( .. :]
+   * Each BeginGroupToken has a pointer to the token where the group
+   * ends. This field is set when scanning the end group token.
+   */
   Link<BeginGroupToken> groupingStack = const Link<BeginGroupToken>();
 
-  ArrayBasedScanner(this.includeComments)
-    : this.extraCharOffset = 0,
-      this.tokenStart = -1,
-      this.byteOffset = -1,
-      this.tokens = new Token(EOF_INFO, -1) {
-    this.tail = this.tokens;
+  /**
+   * Appends a token whose kind is determined by [info] and content is defined
+   * by the String [value].
+   *
+   * This method is invoked for class names, field names, method names, types,
+   * etc.
+   */
+  void appendStringToken(PrecedenceInfo info, String value) {
+    tail.next = new StringToken.fromString(info, value, tokenStart, true);
+    tail = tail.next;
   }
 
-  int advance() {
-    int next = nextByte();
-    return next;
+  /**
+   * Appends a fixed token whose kind and content is determined by [info].
+   * Appends an *operator* token from [info].
+   *
+   * An operator token represent operators like ':', '.', ';', '&&', '==', '--',
+   * '=>', etc.
+   */
+  void appendPrecedenceToken(PrecedenceInfo info) {
+    tail.next = new SymbolToken(info, tokenStart);
+    tail = tail.next;
   }
 
+  /**
+   * Appends a fixed token based on whether the current char is [choice] or not.
+   * If the current char is [choice] a fixed token whose kind and content
+   * is determined by [yes] is appended, otherwise a fixed token whose kind
+   * and content is determined by [no] is appended.
+   */
   int select(int choice, PrecedenceInfo yes, PrecedenceInfo no) {
     int next = advance();
     if (identical(next, choice)) {
@@ -42,27 +56,22 @@
     }
   }
 
-  void appendPrecedenceToken(PrecedenceInfo info) {
-    tail.next = new Token(info, tokenStart);
-    tail = tail.next;
-  }
-
-  void appendStringToken(PrecedenceInfo info, String value) {
-    tail.next = new StringToken(info, value, tokenStart);
-    tail = tail.next;
-  }
-
+  /**
+   * Appends a keyword token whose kind is determined by [keyword].
+   */
   void appendKeywordToken(Keyword keyword) {
     String syntax = keyword.syntax;
-
     // Type parameters and arguments cannot contain 'this' or 'super'.
-    if (identical(syntax, 'this') || identical(syntax, 'super')) discardOpenLt();
+    if (identical(syntax, 'this') || identical(syntax, 'super')) {
+      discardOpenLt();
+    }
     tail.next = new KeywordToken(keyword, tokenStart);
     tail = tail.next;
   }
 
   void appendEofToken() {
-    tail.next = new Token(EOF_INFO, charOffset);
+    beginToken();
+    tail.next = new SymbolToken(EOF_INFO, tokenStart);
     tail = tail.next;
     // EOF points to itself so there's always infinite look-ahead.
     tail.next = tail;
@@ -73,37 +82,54 @@
     }
   }
 
-  void beginToken() {
-    tokenStart = charOffset;
-  }
-
-  Token firstToken() {
-    return tokens.next;
-  }
-
-  Token previousToken() {
-    return tail;
-  }
-
-  void addToCharOffset(int offset) {
-    extraCharOffset += offset;
-  }
-
+  /**
+   * Notifies scanning a whitespace character. Note that [appendWhiteSpace] is
+   * not always invoked for [$SPACE] characters.
+   *
+   * This method is used by the scanners to track line breaks and create the
+   * [lineStarts] map.
+   */
   void appendWhiteSpace(int next) {
-    // Do nothing, we don't collect white space.
+    if (next == $LF && file != null) {
+      lineStarts.add(stringOffset + 1); // +1, the line starts after the $LF.
+    }
   }
 
-  void appendBeginGroup(PrecedenceInfo info, String value) {
-    Token token = new BeginGroupToken(info, value, tokenStart);
+  /**
+   * Notifies on [$LF] characters in multi-line commends or strings.
+   *
+   * This method is used by the scanners to track line breaks and create the
+   * [lineStarts] map.
+   */
+  void lineFeedInMultiline() {
+    if (file != null) {
+      lineStarts.add(stringOffset + 1);
+    }
+  }
+
+  /**
+   * Appends a token that begins a new group, represented by [value].
+   * Group begin tokens are '{', '(', '[' and '${'.
+   */
+  void appendBeginGroup(PrecedenceInfo info) {
+    Token token = new BeginGroupToken(info, tokenStart);
     tail.next = token;
     tail = tail.next;
+
+    // { (  [ ${ cannot appear inside a type parameters / arguments.
     if (!identical(info.kind, LT_TOKEN)) discardOpenLt();
     groupingStack = groupingStack.prepend(token);
   }
 
-  int appendEndGroup(PrecedenceInfo info, String value, int openKind) {
-    assert(!identical(openKind, LT_TOKEN));
-    appendStringToken(info, value);
+  /**
+   * Appends a token that begins a ends group, represented by [value].
+   * It handles the group end tokens '}', ')' and ']'. The tokens '>' and
+   * '>>' are handled separately bo [appendGt] and [appendGtGt].
+   */
+  int appendEndGroup(PrecedenceInfo info, int openKind) {
+    assert(!identical(openKind, LT_TOKEN)); // openKind is < for > and >>
+    appendPrecedenceToken(info);
+    // Don't report unmatched errors for <; it is also the less-than operator.
     discardOpenLt();
     if (groupingStack.isEmpty) {
       return advance();
@@ -113,7 +139,8 @@
       if (!identical(openKind, OPEN_CURLY_BRACKET_TOKEN) ||
           !identical(begin.kind, STRING_INTERPOLATION_TOKEN)) {
         // Not ending string interpolation.
-        return error(new SourceString('Unmatched ${begin.stringValue}'));
+        unmatchedBeginGroup(begin);
+        return advance();
       }
       // We're ending an interpolated expression.
       begin.endGroup = tail;
@@ -127,8 +154,13 @@
     return advance();
   }
 
-  void appendGt(PrecedenceInfo info, String value) {
-    appendStringToken(info, value);
+  /**
+   * Appends a token for '>'.
+   * This method does not issue unmatched errors, because > is also the
+   * greater-than operator. It does not necessarily have to close a group.
+   */
+  void appendGt(PrecedenceInfo info) {
+    appendPrecedenceToken(info);
     if (groupingStack.isEmpty) return;
     if (identical(groupingStack.head.kind, LT_TOKEN)) {
       groupingStack.head.endGroup = tail;
@@ -136,10 +168,17 @@
     }
   }
 
-  void appendGtGt(PrecedenceInfo info, String value) {
-    appendStringToken(info, value);
+  /**
+   * Appends a token for '>>'.
+   * This method does not issue unmatched errors, because >> is also the
+   * shift operator. It does not necessarily have to close a group.
+   */
+  void appendGtGt(PrecedenceInfo info) {
+    appendPrecedenceToken(info);
     if (groupingStack.isEmpty) return;
     if (identical(groupingStack.head.kind, LT_TOKEN)) {
+      // Don't assign endGroup: in "T<U<V>>", the '>>' token closes the outer
+      // '<', the inner '<' is left without endGroup.
       groupingStack = groupingStack.tail;
     }
     if (groupingStack.isEmpty) return;
@@ -149,35 +188,27 @@
     }
   }
 
-  void appendGtGtGt(PrecedenceInfo info, String value) {
-    appendStringToken(info, value);
-    if (groupingStack.isEmpty) return;
-    if (identical(groupingStack.head.kind, LT_TOKEN)) {
-      groupingStack = groupingStack.tail;
-    }
-    if (groupingStack.isEmpty) return;
-    if (identical(groupingStack.head.kind, LT_TOKEN)) {
-      groupingStack = groupingStack.tail;
-    }
-    if (groupingStack.isEmpty) return;
-    if (identical(groupingStack.head.kind, LT_TOKEN)) {
-      groupingStack.head.endGroup = tail;
-      groupingStack = groupingStack.tail;
-    }
-  }
-
-  void appendComment() {
+  void appendComment(start, bool asciiOnly) {
     if (!includeComments) return;
-    SourceString value = utf8String(tokenStart, -1);
-    appendByteStringToken(COMMENT_INFO, value);
+    appendSubstringToken(COMMENT_INFO, start, asciiOnly);
   }
 
+  /**
+   * We call this method to discard '<' from the "grouping" stack
+   * (maintained by subclasses).
+   *
+   * [PartialParser.skipExpression] relies on the fact that we do not
+   * create groups for stuff like:
+   * [:a = b < c, d = e > f:].
+   *
+   * In other words, this method is called when the scanner recognizes
+   * something which cannot possibly be part of a type
+   * parameter/argument list.
+   */
   void discardOpenLt() {
     while (!groupingStack.isEmpty
         && identical(groupingStack.head.kind, LT_TOKEN)) {
       groupingStack = groupingStack.tail;
     }
   }
-
-  void unmatchedBeginGroup(BeginGroupToken begin);
-}
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/byte_array_scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/byte_array_scanner.dart
deleted file mode 100644
index 4cf9eeb..0000000
--- a/sdk/lib/_internal/compiler/implementation/scanner/byte_array_scanner.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2011, 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 parser;
-
-/**
- * Scanner that reads from a byte array and creates tokens that points
- * to the same array.
- */
-class ByteArrayScanner extends ArrayBasedScanner<ByteString> {
-  final List<int> bytes;
-
-  ByteArrayScanner(List<int> this.bytes, [bool includeComments = false])
-    : super(includeComments);
-
-  int nextByte() => byteAt(++byteOffset);
-
-  int peek() => byteAt(byteOffset + 1);
-
-  int byteAt(int index) => bytes[index];
-
-  AsciiString asciiString(int start, int offset) {
-    return AsciiString.of(bytes, start, byteOffset - start + offset);
-  }
-
-  Utf8String utf8String(int start, int offset) {
-    return Utf8String.of(bytes, start, byteOffset - start + offset + 1);
-  }
-
-  void appendByteStringToken(PrecedenceInfo info, ByteString value) {
-    tail.next = new ByteStringToken(info, value, tokenStart);
-    tail = tail.next;
-  }
-
-  // This method should be equivalent to the one in super. However,
-  // this is a *HOT* method and Dart VM performs better if it is easy
-  // to inline.
-  int advance() => bytes[++byteOffset];
-}
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart b/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
deleted file mode 100644
index 543cd6c..0000000
--- a/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright (c) 2011, 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 parser;
-
-/**
- * An abstract string representation.
- */
-abstract class ByteString extends IterableBase<int> implements SourceString {
-  final List<int> bytes;
-  final int offset;
-  final int length;
-  int _hashCode;
-
-  ByteString(List<int> this.bytes, int this.offset, int this.length);
-
-  String get charset;
-
-  String slowToString() => new String.fromCharCodes(
-      new Utf8Decoder(bytes, offset, length).decodeRest());
-
-  String toString() => "ByteString(${slowToString()})";
-
-  bool operator ==(other) {
-    throw "should be overridden in subclass";
-  }
-
-  Iterator<int> get iterator => new Utf8Decoder(bytes, offset, length);
-
-  int get hashCode {
-    if (_hashCode == null) {
-      _hashCode = computeHashCode();
-    }
-    return _hashCode;
-  }
-
-  int computeHashCode() {
-    int code = 1;
-    int end = offset + length;
-    for (int i = offset; i < end; i++) {
-      code += 19 * code + bytes[i];
-    }
-    return code;
-  }
-
-  printOn(StringBuffer sb) {
-    sb.write(slowToString());
-  }
-
-  bool get isEmpty => length == 0;
-  bool isPrivate() => !isEmpty && identical(bytes[offset], $_);
-
-  String get stringValue => null;
-}
-
-/**
- * A string that consists purely of 7bit ASCII characters.
- */
-class AsciiString extends ByteString {
-  final String charset = "ASCII";
-
-  AsciiString(List<int> bytes, int offset, int length)
-    : super(bytes, offset, length);
-
-  static AsciiString of(List<int> bytes, int offset, int length) {
-    AsciiString string = new AsciiString(bytes, offset, length);
-    return string;
-  }
-
-  Iterator<int> get iterator => new AsciiStringIterator(bytes);
-
-  SourceString copyWithoutQuotes(int initial, int terminal) {
-    return new AsciiString(bytes, offset + initial,
-                           length - initial - terminal);
-  }
-
-
-  static AsciiString fromString(String string) {
-    List<int> bytes = string.codeUnits;
-    return AsciiString.of(bytes, 0, bytes.length);
-  }
-}
-
-
-class AsciiStringIterator implements Iterator<int> {
-  final List<int> bytes;
-  int offset;
-  final int end;
-  int _current;
-
-  AsciiStringIterator(List<int> bytes)
-      : this.bytes = bytes, offset = 0, end = bytes.length;
-  AsciiStringIterator.range(List<int> bytes, int from, int length)
-      : this.bytes = bytes, offset = from, end = from + length;
-
-  int get current => _current;
-  bool moveNext() {
-    if (offset < end) {
-      _current = bytes[offset++];
-      return true;
-    }
-    _current = null;
-    return false;
-  }
-}
-
-
-/**
- * A string that consists of characters that can be encoded as UTF-8.
- */
-class Utf8String extends ByteString {
-  final String charset = "UTF8";
-
-  Utf8String(List<int> bytes, int offset, int length)
-    : super(bytes, offset, length);
-
-  static Utf8String of(List<int> bytes, int offset, int length) {
-    return new Utf8String(bytes, offset, length);
-  }
-
-  static Utf8String fromString(String string) {
-    throw "not implemented yet";
-  }
-
-  Iterator<int> get iterator => new Utf8Decoder(bytes, 0, length);
-
-  SourceString copyWithoutQuotes(int initial, int terminal) {
-    assert((){
-      // Only allow dropping ASCII characters, to guarantee that
-      // the resulting Utf8String is still valid.
-      for (int i = 0; i < initial; i++) {
-        if (bytes[offset + i] >= 0x80) return false;
-      }
-      for (int i = 0; i < terminal; i++) {
-        if (bytes[offset + length - terminal + i] >= 0x80) return false;
-      }
-      return true;
-    });
-    // TODO(lrn): Check that first and last bytes use the same type of quotes.
-    return new Utf8String(bytes, offset + initial,
-                          length - initial - terminal);
-  }
-}
-
-/**
- * A ByteString-valued token.
- */
-class ByteStringToken extends Token {
-  final ByteString value;
-
-  ByteStringToken(PrecedenceInfo info, ByteString this.value, int charOffset)
-    : super(info, charOffset);
-
-  String toString() => value.toString();
-}
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart
index 9cb1736..689f844 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart
@@ -15,7 +15,7 @@
   final Token endToken;
   ClassNode cachedNode;
 
-  PartialClassElement(SourceString name,
+  PartialClassElement(String name,
                       Token this.beginToken,
                       Token this.endToken,
                       Element enclosing,
@@ -76,7 +76,7 @@
         enclosingElement.kind != ElementKind.CLASS) {
       return false;
     }
-    SourceString name;
+    String name;
     if (nameNode.asIdentifier() != null) {
       name = nameNode.asIdentifier().source;
     } else {
@@ -87,17 +87,17 @@
   }
 
   // TODO(johnniwinther): Remove this method.
-  SourceString getMethodNameHack(Node methodName) {
+  String getMethodNameHack(Node methodName) {
     Send send = methodName.asSend();
     if (send == null) {
-      if (isConstructorName(methodName)) return const SourceString('');
+      if (isConstructorName(methodName)) return '';
       return methodName.asIdentifier().source;
     }
     Identifier receiver = send.receiver.asIdentifier();
     Identifier selector = send.selector.asIdentifier();
     Operator operator = selector.asOperator();
     if (operator != null) {
-      assert(identical(receiver.source.stringValue, 'operator'));
+      assert(identical(receiver.source, 'operator'));
       // TODO(ahe): It is a hack to compare to ')', but it beats
       // parsing the node.
       bool isUnary = identical(operator.token.next.next.stringValue, ')');
@@ -117,7 +117,7 @@
     FunctionExpression method = popNode();
     pushNode(null);
     bool isConstructor = isConstructorName(method.name);
-    SourceString name = getMethodNameHack(method.name);
+    String name = getMethodNameHack(method.name);
     ElementKind kind = ElementKind.FUNCTION;
     if (isConstructor) {
       if (getOrSet != null) {
@@ -138,7 +138,7 @@
     super.endFactoryMethod(beginToken, endToken);
     FunctionExpression method = popNode();
     pushNode(null);
-    SourceString name = getMethodNameHack(method.name);
+    String name = getMethodNameHack(method.name);
     Identifier singleIdentifierName = method.name.asIdentifier();
     if (singleIdentifierName != null && singleIdentifierName.source == name) {
       if (name != enclosingElement.name) {
@@ -159,7 +159,7 @@
     VariableDefinitions variableDefinitions = popNode();
     Modifiers modifiers = variableDefinitions.modifiers;
     pushNode(null);
-    void buildFieldElement(SourceString name, Element fields) {
+    void buildFieldElement(String name, Element fields) {
       Element element =
           new VariableElementX(name, fields, ElementKind.FIELD, null);
       addMember(element);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart b/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
index cca2e51..d447029 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
@@ -7,7 +7,7 @@
 /**
  * A keyword in the Dart programming language.
  */
-class Keyword extends IterableBase<int> implements SourceString {
+class Keyword {
   static const List<Keyword> values = const <Keyword> [
       const Keyword("assert"),
       const Keyword("break"),
@@ -81,10 +81,10 @@
     return _keywords;
   }
 
-  const Keyword(String this.syntax,
-                {bool this.isPseudo: false,
-                 bool this.isBuiltIn: false,
-                 PrecedenceInfo this.info: KEYWORD_INFO});
+  const Keyword(this.syntax,
+                {this.isPseudo: false,
+                 this.isBuiltIn: false,
+                 this.info: KEYWORD_INFO});
 
   static Map<String, Keyword> computeKeywordMap() {
     Map<String, Keyword> result = new Map<String, Keyword>();
@@ -94,29 +94,7 @@
     return result;
   }
 
-  int get hashCode => syntax.hashCode;
-
-  bool operator ==(other) {
-    return other is SourceString && toString() == other.slowToString();
-  }
-
-  Iterator<int> get iterator => new StringCodeIterator(syntax);
-
-  void printOn(StringBuffer sb) {
-    sb.write(syntax);
-  }
-
   String toString() => syntax;
-  String slowToString() => syntax;
-  String get stringValue => syntax;
-
-  SourceString copyWithoutQuotes(int initial, int terminal) {
-    // TODO(lrn): consider remodelling to avoid having this method in keywords.
-    return this;
-  }
-
-  bool get isEmpty => false;
-  bool isPrivate() => false;
 }
 
 /**
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
index bb77a50..be3ca45 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -534,56 +534,56 @@
   }
 
   Token expected(String string, Token token) {
-    error("expected '$string', but got '${token.slowToString()}'", token);
+    error("expected '$string', but got '${token.value}'", token);
     return skipToEof(token);
   }
 
   void expectedIdentifier(Token token) {
-    error("expected identifier, but got '${token.slowToString()}'", token);
+    error("expected identifier, but got '${token.value}'", token);
   }
 
   Token expectedType(Token token) {
-    error("expected a type, but got '${token.slowToString()}'", token);
+    error("expected a type, but got '${token.value}'", token);
     return skipToEof(token);
   }
 
   Token expectedExpression(Token token) {
-    error("expected an expression, but got '${token.slowToString()}'", token);
+    error("expected an expression, but got '${token.value}'", token);
     return skipToEof(token);
   }
 
   Token unexpected(Token token) {
-    error("unexpected token '${token.slowToString()}'", token);
+    error("unexpected token '${token.value}'", token);
     return skipToEof(token);
   }
 
   Token expectedBlockToSkip(Token token) {
-    error("expected a block, but got '${token.slowToString()}'", token);
+    error("expected a block, but got '${token.value}'", token);
     return skipToEof(token);
   }
 
   Token expectedFunctionBody(Token token) {
-    error("expected a function body, but got '${token.slowToString()}'", token);
+    error("expected a function body, but got '${token.value}'", token);
     return skipToEof(token);
   }
 
   Token expectedClassBody(Token token) {
-    error("expected a class body, but got '${token.slowToString()}'", token);
+    error("expected a class body, but got '${token.value}'", token);
     return skipToEof(token);
   }
 
   Token expectedClassBodyToSkip(Token token) {
-    error("expected a class body, but got '${token.slowToString()}'", token);
+    error("expected a class body, but got '${token.value}'", token);
     return skipToEof(token);
   }
 
   Link<Token> expectedDeclaration(Token token) {
-    error("expected a declaration, but got '${token.slowToString()}'", token);
+    error("expected a declaration, but got '${token.value}'", token);
     return const Link<Token>();
   }
 
   Token unmatched(Token token) {
-    error("unmatched '${token.slowToString()}'", token);
+    error("unmatched '${token.value}'", token);
     return skipToEof(token);
   }
 
@@ -767,7 +767,7 @@
   void endClassDeclaration(int interfacesCount, Token beginToken,
                            Token extendsKeyword, Token implementsKeyword,
                            Token endToken) {
-    SourceString nativeTagInfo = native.checkForNativeClass(this);
+    String nativeTagInfo = native.checkForNativeClass(this);
     NodeList interfaces =
         makeNodeList(interfacesCount, implementsKeyword, null, ",");
     Node supertype = popNode();
@@ -782,8 +782,8 @@
   }
 
   void rejectBuiltInIdentifier(Identifier name) {
-    if (name.source is Keyword) {
-      Keyword keyword = name.source;
+    if (name.token is KeywordToken) {
+      Keyword keyword = (name.token as KeywordToken).keyword;
       if (!keyword.isPseudo) {
         recoverableError('illegal name ${keyword.syntax}', node: name);
       }
@@ -847,7 +847,7 @@
   }
 
   void endTopLevelFields(int count, Token beginToken, Token endToken) {
-    void buildFieldElement(SourceString name, Element fields) {
+    void buildFieldElement(String name, Element fields) {
       pushElement(new VariableElementX(name, fields, ElementKind.FIELD, null));
     }
     NodeList variables = makeNodeList(count, null, null, ",");
@@ -861,7 +861,7 @@
   void buildFieldElements(Modifiers modifiers,
                           NodeList variables,
                           Element enclosingElement,
-                          void buildFieldElement(SourceString name,
+                          void buildFieldElement(String name,
                                                  Element fields),
                           Token beginToken, Token endToken) {
     Element fields = new PartialFieldListElement(beginToken,
@@ -876,7 +876,7 @@
       if (identifier == null) {
         identifier = initializedIdentifier.asSendSet().selector.asIdentifier();
       }
-      SourceString name = identifier.source;
+      String name = identifier.source;
       buildFieldElement(name, fields);
     }
   }
@@ -943,33 +943,33 @@
   }
 
   Token expected(String string, Token token) {
-    listener.cancel("expected '$string', but got '${token.slowToString()}'",
+    listener.cancel("expected '$string', but got '${token.value}'",
                     token: token);
     return skipToEof(token);
   }
 
   void expectedIdentifier(Token token) {
-    listener.cancel("expected identifier, but got '${token.slowToString()}'",
+    listener.cancel("expected identifier, but got '${token.value}'",
                     token: token);
     pushNode(null);
   }
 
   Token expectedType(Token token) {
-    listener.cancel("expected a type, but got '${token.slowToString()}'",
+    listener.cancel("expected a type, but got '${token.value}'",
                     token: token);
     pushNode(null);
     return skipToEof(token);
   }
 
   Token expectedExpression(Token token) {
-    listener.cancel("expected an expression, but got '${token.slowToString()}'",
+    listener.cancel("expected an expression, but got '${token.value}'",
                     token: token);
     pushNode(null);
     return skipToEof(token);
   }
 
   Token unexpected(Token token) {
-    String message = "unexpected token '${token.slowToString()}'";
+    String message = "unexpected token '${token.value}'";
     if (token.info == BAD_INPUT_INFO) {
       message = token.stringValue;
     }
@@ -986,14 +986,14 @@
   }
 
   Token expectedFunctionBody(Token token) {
-    String printString = token.slowToString();
+    String printString = token.value;
     listener.cancel("expected a function body, but got '$printString'",
                     token: token);
     return skipToEof(token);
   }
 
   Token expectedClassBody(Token token) {
-    listener.cancel("expected a class body, but got '${token.slowToString()}'",
+    listener.cancel("expected a class body, but got '${token.value}'",
                     token: token);
     return skipToEof(token);
   }
@@ -1007,13 +1007,13 @@
   }
 
   Link<Token> expectedDeclaration(Token token) {
-    listener.cancel("expected a declaration, but got '${token.slowToString()}'",
+    listener.cancel("expected a declaration, but got '${token.value}'",
                     token: token);
     return const Link<Token>();
   }
 
   Token unmatched(Token token) {
-    listener.cancel("unmatched '${token.slowToString()}'", token: token);
+    listener.cancel("unmatched '${token.value}'", token: token);
     return skipToEof(token);
   }
 
@@ -1080,13 +1080,11 @@
       // in correct (source) order.
       poppedNodes = poppedNodes.prepend(popNode());
     }
-    SourceString sourceDelimiter =
-        (delimiter == null) ? null : new SourceString(delimiter);
-    return new NodeList(beginToken, poppedNodes, endToken, sourceDelimiter);
+    return new NodeList(beginToken, poppedNodes, endToken, delimiter);
   }
 
   void beginLiteralString(Token token) {
-    SourceString source = token.value;
+    String source = token.value;
     StringQuoting quoting = StringValidator.quotingFromString(source);
     pushQuoting(quoting);
     // Just wrap the token for now. At the end of the interpolation,
@@ -1131,8 +1129,7 @@
     if (isLast) {
       pushNode(string);
     } else {
-      NodeList partNodes =
-          new NodeList(null, parts, null, const SourceString(""));
+      NodeList partNodes = new NodeList(null, parts, null, "");
       pushNode(new StringInterpolation(string, partNodes));
     }
   }
@@ -1328,7 +1325,7 @@
       return native.handleNativeFunctionBody(this, token);
     } else {
       listener.cancel(
-          "expected a function body, but got '${token.slowToString()}'",
+          "expected a function body, but got '${token.value}'",
           token: token);
       return skipToEof(token);
     }
@@ -1339,7 +1336,7 @@
       return native.handleNativeClassBody(this, token);
     } else {
       listener.cancel(
-          "expected a class body, but got '${token.slowToString()}'",
+          "expected a class body, but got '${token.value}'",
           token: token);
       return skipToEof(token);
     }
@@ -1637,8 +1634,8 @@
     NodeList arguments =
         makeNodeList(1, openSquareBracket, closeSquareBracket, null);
     Node receiver = popNode();
-    Token token =
-      new StringToken(INDEX_INFO, '[]', openSquareBracket.charOffset);
+    Token token = new StringToken.fromString(INDEX_INFO, '[]',
+                                  openSquareBracket.charOffset);
     Node selector = new Operator(token);
     pushNode(new Send(receiver, selector, arguments));
   }
@@ -1888,7 +1885,7 @@
   final Token getOrSet;
   final Token endToken;
 
-  PartialFunctionElement(SourceString name,
+  PartialFunctionElement(String name,
                          Token this.beginToken,
                          Token this.getOrSet,
                          Token this.endToken,
@@ -1964,7 +1961,7 @@
 class PartialTypedefElement extends TypedefElementX {
   final Token token;
 
-  PartialTypedefElement(SourceString name, Element enclosing, this.token)
+  PartialTypedefElement(String name, Element enclosing, this.token)
       : super(name, enclosing);
 
   Node parseNode(DiagnosticListener listener) {
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
index fd718be5..0750ff3 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
@@ -398,8 +398,8 @@
     final kind = token.kind;
     if (identical(kind, IDENTIFIER_TOKEN)) return true;
     if (identical(kind, KEYWORD_TOKEN)) {
-      Keyword keyword = token.value;
-      String value = keyword.stringValue;
+      Keyword keyword = (token as KeywordToken).keyword;
+      String value = keyword.syntax;
       return keyword.isPseudo
           || (identical(value, 'dynamic'))
           || (identical(value, 'void'));
@@ -637,12 +637,12 @@
       } while (optional(',', token));
       Token next = token.next;
       if (identical(token.stringValue, '>>')) {
-        token = new Token(GT_INFO, token.charOffset);
-        token.next = new Token(GT_INFO, token.charOffset + 1);
+        token = new SymbolToken(GT_INFO, token.charOffset);
+        token.next = new SymbolToken(GT_INFO, token.charOffset + 1);
         token.next.next = next;
       } else if (identical(token.stringValue, '>>>')) {
-        token = new Token(GT_INFO, token.charOffset);
-        token.next = new Token(GT_GT_INFO, token.charOffset + 1);
+        token = new SymbolToken(GT_INFO, token.charOffset);
+        token.next = new SymbolToken(GT_GT_INFO, token.charOffset + 1);
         token.next.next = next;
       }
       endStuff(count, begin, token);
@@ -1672,6 +1672,7 @@
     if (identical(value, '+')) {
       // Dart no longer allows prefix-plus.
       listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS);
+      return parseUnaryExpression(token.next, allowCascades);
     } else if ((identical(value, '!')) ||
                (identical(value, '-')) ||
                (identical(value, '~'))) {
@@ -1778,7 +1779,7 @@
   }
 
   Token parseParenthesizedExpression(Token token) {
-    var begin = token;
+    var begin = (token as BeginGroupToken);
     token = expect('(', token);
     token = parseExpression(token);
     if (!identical(begin.endGroup, token)) {
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
index 16c2384..771290b 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
@@ -6,88 +6,185 @@
 
 abstract class Scanner {
   Token tokenize();
+
+  factory Scanner(SourceFile file, {bool includeComments: false}) {
+    if (file is Utf8BytesSourceFile) {
+      return new Utf8BytesScanner(file, includeComments: includeComments);
+    } else {
+      return new StringScanner(file, includeComments: includeComments);
+    }
+  }
 }
 
-/**
- * Common base class for a Dart scanner.
- */
-abstract class AbstractScanner<T extends SourceString> implements Scanner {
-  int advance();
-  int nextByte();
+abstract class AbstractScanner implements Scanner {
+  final bool includeComments;
 
   /**
-   * Returns the current character or byte depending on the underlying input
-   * kind. For example, [StringScanner] operates on [String] and thus returns
-   * characters (Unicode codepoints represented as int) whereas
-   * [ByteArrayScanner] operates on byte arrays and thus returns bytes.
+   * The string offset for the next token that will be created.
+   *
+   * Note that in the [Utf8BytesScanner], [stringOffset] and [scanOffset] values
+   * are different. One string character can be encoded using multiple UTF-8
+   * bytes.
+   */
+  int tokenStart = -1;
+
+  /**
+   * A pointer to the token stream created by this scanner. The first token
+   * is a special token and not part of the source file. This is an
+   * implementation detail to avoids special cases in the scanner. This token
+   * is not exposed to clients of the scanner, which are expected to invoke
+   * [firstToken] to access the token stream.
+   */
+  final Token tokens = new SymbolToken(EOF_INFO, -1);
+
+  /**
+   * A pointer to the last scanned token.
+   */
+  Token tail;
+
+  /**
+   * The source file that is being scanned. This field can be [:null:].
+   * If the source file is available, the scanner assigns its [:lineStarts:] and
+   * [:length:] fields at the end of [tokenize].
+   */
+  final SourceFile file;
+
+  final List<int> lineStarts = [0];
+
+  AbstractScanner(this.file, this.includeComments) {
+    this.tail = this.tokens;
+  }
+
+
+  /**
+   * Advances and returns the next character.
+   *
+   * If the next character is non-ASCII, then the returned value depends on the
+   * scanner implementation. The [Utf8BytesScanner] returns a UTF-8 byte, while
+   * the [StringScanner] returns a UTF-16 code unit.
+   *
+   * The scanner ensures that [advance] is not invoked after it returned [$EOF].
+   * This allows implementations to omit bound checks if the data structure ends
+   * with '0'.
+   */
+  int advance();
+
+  /**
+   * Returns the current unicode character.
+   *
+   * If the current character is ASCII, then it is returned unchanged.
+   *
+   * The [Utf8BytesScanner] decodes the next unicode code point starting at the
+   * current position. Note that every unicode character is returned as a single
+   * code point, i.e., for '\u{1d11e}' it returns 119070, and the following
+   * [advance] returns the next character.
+   *
+   * The [StringScanner] returns the current character unchanged, which might
+   * be a surrogate character. In the case of '\u{1d11e}', it returns the first
+   * code unit 55348, and the following [advance] returns the second code unit
+   * 56606.
+   *
+   * Invoking [currentAsUnicode] multiple times is safe, i.e.,
+   * [:currentAsUnicode(next) == currentAsUnicode(currentAsUnicode(next)):].
+   */
+  int currentAsUnicode(int next);
+
+  /**
+   * Returns the character at the next poisition. Like in [advance], the
+   * [Utf8BytesScanner] returns a UTF-8 byte, while the [StringScanner] returns
+   * a UTF-16 code unit.
    */
   int peek();
 
   /**
-   * Appends a fixed token based on whether the current char is [choice] or not.
-   * If the current char is [choice] a fixed token whose kind and content
-   * is determined by [yes] is appended, otherwise a fixed token whose kind
-   * and content is determined by [no] is appended.
+   * Notifies the scanner that unicode characters were detected in either a
+   * comment or a string literal between [startScanOffset] and the current
+   * scan offset.
    */
-  int select(int choice, PrecedenceInfo yes, PrecedenceInfo no);
+  void handleUnicode(int startScanOffset);
 
   /**
-   * Appends a fixed token whose kind and content is determined by [info].
+   * Returns the current scan offset.
+   *
+   * In the [Utf8BytesScanner] this is the offset into the byte list, in the
+   * [StringScanner] the offset in the source string.
    */
-  void appendPrecedenceToken(PrecedenceInfo info);
+  int get scanOffset;
 
   /**
-   * Appends a token whose kind is determined by [info] and content is [value].
+   * Returns the current string offset.
+   *
+   * In the [StringScanner] this is identical to the [scanOffset]. In the
+   * [Utf8BytesScanner] it is computed based on encountered UTF-8 characters.
    */
+  int get stringOffset;
+
+  /**
+   * Returns the first token scanned by this [Scanner].
+   */
+  Token firstToken();
+
+  /**
+   * Returns the last token scanned by this [Scanner].
+   */
+  Token previousToken();
+
+  /**
+   * Notifies that a new token starts at current offset.
+   */
+  void beginToken() {
+    tokenStart = stringOffset;
+  }
+
+  /**
+   * Appends a substring from the scan offset [:start:] to the current
+   * [:scanOffset:] plus the [:extraOffset:]. For example, if the current
+   * scanOffset is 10, then [:appendSubstringToken(5, -1):] will append the
+   * substring string [5,9).
+   *
+   * Note that [extraOffset] can only be used if the covered character(s) are
+   * known to be ASCII.
+   */
+  void appendSubstringToken(PrecedenceInfo info, int start,
+                            bool asciiOnly, [int extraOffset]);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
   void appendStringToken(PrecedenceInfo info, String value);
 
-  /**
-   * Appends a token whose kind is determined by [info] and content is defined
-   * by the SourceString [value].
-   */
-  void appendByteStringToken(PrecedenceInfo info, T value);
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  void appendPrecedenceToken(PrecedenceInfo info);
 
-  /**
-   * Appends a keyword token whose kind is determined by [keyword].
-   */
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  int select(int choice, PrecedenceInfo yes, PrecedenceInfo no);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
   void appendKeywordToken(Keyword keyword);
-  void appendWhiteSpace(int next);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
   void appendEofToken();
 
-  /**
-   * Creates an ASCII SourceString whose content begins at the source byte
-   * offset [start] and ends at [offset] bytes from the current byte offset of
-   * the scanner. For example, if the current byte offset is 10,
-   * [:asciiString(0,-1):] creates an ASCII SourceString whose content is found
-   * at the [0,9[ byte interval of the source text.
-   */
-  T asciiString(int start, int offset);
-  T utf8String(int start, int offset);
-  Token firstToken();
-  Token previousToken();
-  void beginToken();
-  void addToCharOffset(int offset);
-  int get charOffset;
-  int get byteOffset;
-  void appendBeginGroup(PrecedenceInfo info, String value);
-  int appendEndGroup(PrecedenceInfo info, String value, int openKind);
-  void appendGt(PrecedenceInfo info, String value);
-  void appendGtGt(PrecedenceInfo info, String value);
-  void appendGtGtGt(PrecedenceInfo info, String value);
-  void appendComment();
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  void appendWhiteSpace(int next);
 
-  /**
-   * We call this method to discard '<' from the "grouping" stack
-   * (maintained by subclasses).
-   *
-   * [PartialParser.skipExpression] relies on the fact that we do not
-   * create groups for stuff like:
-   * [:a = b < c, d = e > f:].
-   *
-   * In other words, this method is called when the scanner recognizes
-   * something which cannot possibly be part of a type
-   * parameter/argument list.
-   */
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  void lineFeedInMultiline();
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  void appendBeginGroup(PrecedenceInfo info);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  int appendEndGroup(PrecedenceInfo info, int openKind);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  void appendGt(PrecedenceInfo info);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  void appendGtGt(PrecedenceInfo info);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
+  void appendComment(start, bool asciiOnly);
+
+  /** Documentation in subclass [ArrayBasedScanner]. */
   void discardOpenLt();
 
   // TODO(ahe): Move this class to implementation.
@@ -98,6 +195,14 @@
       next = bigSwitch(next);
     }
     appendEofToken();
+
+    if (file != null) {
+      file.length = stringOffset;
+      // One additional line start at the end, see [SourceFile.lineStarts].
+      lineStarts.add(stringOffset + 1);
+      file.lineStarts = lineStarts;
+    }
+
     return firstToken();
   }
 
@@ -107,8 +212,10 @@
         || identical(next, $LF) || identical(next, $CR)) {
       appendWhiteSpace(next);
       next = advance();
+      // Sequences of spaces are common, so advance through them fast.
       while (identical(next, $SPACE)) {
-        appendWhiteSpace(next);
+        // We don't invoke [:appendWhiteSpace(next):] here for efficiency,
+        // assuming that it does not do anything for space characters.
         next = advance();
       }
       return next;
@@ -121,8 +228,10 @@
       return tokenizeKeywordOrIdentifier(next, true);
     }
 
-    if (($A <= next && next <= $Z) || identical(next, $_) || identical(next, $$)) {
-      return tokenizeIdentifier(next, byteOffset, true);
+    if (($A <= next && next <= $Z) ||
+        identical(next, $_) ||
+        identical(next, $$)) {
+      return tokenizeIdentifier(next, scanOffset, true);
     }
 
     if (identical(next, $LT)) {
@@ -187,12 +296,12 @@
     }
 
     if (identical(next, $OPEN_PAREN)) {
-      appendBeginGroup(OPEN_PAREN_INFO, "(");
+      appendBeginGroup(OPEN_PAREN_INFO);
       return advance();
     }
 
     if (identical(next, $CLOSE_PAREN)) {
-      return appendEndGroup(CLOSE_PAREN_INFO, ")", OPEN_PAREN_TOKEN);
+      return appendEndGroup(CLOSE_PAREN_INFO, OPEN_PAREN_TOKEN);
     }
 
     if (identical(next, $COMMA)) {
@@ -218,7 +327,7 @@
     }
 
     if (identical(next, $CLOSE_SQUARE_BRACKET)) {
-      return appendEndGroup(CLOSE_SQUARE_BRACKET_INFO, "]",
+      return appendEndGroup(CLOSE_SQUARE_BRACKET_INFO,
                             OPEN_SQUARE_BRACKET_TOKEN);
     }
 
@@ -228,12 +337,12 @@
     }
 
     if (identical(next, $OPEN_CURLY_BRACKET)) {
-      appendBeginGroup(OPEN_CURLY_BRACKET_INFO, "{");
+      appendBeginGroup(OPEN_CURLY_BRACKET_INFO);
       return advance();
     }
 
     if (identical(next, $CLOSE_CURLY_BRACKET)) {
-      return appendEndGroup(CLOSE_CURLY_BRACKET_INFO, "}",
+      return appendEndGroup(CLOSE_CURLY_BRACKET_INFO,
                             OPEN_CURLY_BRACKET_TOKEN);
     }
 
@@ -246,7 +355,7 @@
     }
 
     if (identical(next, $DQ) || identical(next, $SQ)) {
-      return tokenizeString(next, byteOffset, false);
+      return tokenizeString(next, scanOffset, false);
     }
 
     if (identical(next, $PERIOD)) {
@@ -268,9 +377,11 @@
       return $EOF;
     }
     if (next < 0x1f) {
-      return error(new SourceString("unexpected character $next"));
+      return error("unexpected character $next");
     }
 
+    next = currentAsUnicode(next);
+
     // The following are non-ASCII characters.
 
     if (identical(next, $NBSP)) {
@@ -278,16 +389,22 @@
       return advance();
     }
 
-    return tokenizeIdentifier(next, byteOffset, true);
+    return error("unexpected unicode character $next");
   }
 
   int tokenizeTag(int next) {
     // # or #!.*[\n\r]
-    if (byteOffset == 0) {
+    if (scanOffset == 0) {
       if (identical(peek(), $BANG)) {
+        int start = scanOffset + 1;
+        bool asciiOnly = true;
         do {
           next = advance();
-        } while (!identical(next, $LF) && !identical(next, $CR) && !identical(next, $EOF));
+          if (next > 127) asciiOnly = false;
+        } while (!identical(next, $LF) &&
+                 !identical(next, $CR) &&
+                 !identical(next, $EOF));
+        if (!asciiOnly) handleUnicode(start);
         return next;
       }
     }
@@ -311,11 +428,12 @@
     next = advance();
     if (identical(next, $CLOSE_SQUARE_BRACKET)) {
       Token token = previousToken();
-      if (token is KeywordToken && identical(token.value.stringValue, 'operator')) {
+      if (token is KeywordToken &&
+          identical((token as KeywordToken).keyword.syntax, 'operator')) {
         return select($EQ, INDEX_EQ_INFO, INDEX_INFO);
       }
     }
-    appendBeginGroup(OPEN_SQUARE_BRACKET_INFO, "[");
+    appendBeginGroup(OPEN_SQUARE_BRACKET_INFO);
     return next;
   }
 
@@ -379,7 +497,6 @@
     }
   }
 
-
   int tokenizePlus(int next) {
     // + ++ +=
     next = advance();
@@ -396,7 +513,9 @@
   }
 
   int tokenizeExclamation(int next) {
-    // ! != !==
+    // ! !=
+    // !== is kept for user-friendly error reporting.
+
     next = advance();
     if (identical(next, $EQ)) {
       return select($EQ, BANG_EQ_EQ_INFO, BANG_EQ_INFO);
@@ -406,7 +525,8 @@
   }
 
   int tokenizeEquals(int next) {
-    // = == ===
+    // = == =>
+    // === is kept for user-friendly error reporting.
 
     // Type parameters and arguments cannot contain any token that
     // starts with '='.
@@ -424,7 +544,7 @@
   }
 
   int tokenizeGreaterThan(int next) {
-    // > >= >> >>= >>> >>>=
+    // > >= >> >>=
     next = advance();
     if (identical($EQ, next)) {
       appendPrecedenceToken(GT_EQ_INFO);
@@ -435,11 +555,11 @@
         appendPrecedenceToken(GT_GT_EQ_INFO);
         return advance();
       } else {
-        appendGtGt(GT_GT_INFO, ">>");
+        appendGtGt(GT_GT_INFO);
         return next;
       }
     } else {
-      appendGt(GT_INFO, ">");
+      appendGt(GT_INFO);
       return next;
     }
   }
@@ -453,13 +573,13 @@
     } else if (identical($LT, next)) {
       return select($EQ, LT_LT_EQ_INFO, LT_LT_INFO);
     } else {
-      appendBeginGroup(LT_INFO, "<");
+      appendBeginGroup(LT_INFO);
       return next;
     }
   }
 
   int tokenizeNumber(int next) {
-    int start = byteOffset;
+    int start = scanOffset;
     while (true) {
       next = advance();
       if ($0 <= next && next <= $9) {
@@ -473,7 +593,7 @@
             return tokenizeFractionPart(advance(), start);
           }
         }
-        appendByteStringToken(INT_INFO, asciiString(start, 0));
+        appendSubstringToken(INT_INFO, start, true);
         return next;
       }
     }
@@ -482,14 +602,14 @@
   int tokenizeHexOrNumber(int next) {
     int x = peek();
     if (identical(x, $x) || identical(x, $X)) {
-      advance();
-      return tokenizeHex(x);
+      return tokenizeHex(next);
     }
     return tokenizeNumber(next);
   }
 
   int tokenizeHex(int next) {
-    int start = byteOffset - 1;
+    int start = scanOffset;
+    next = advance(); // Advance past the $x or $X.
     bool hasDigits = false;
     while (true) {
       next = advance();
@@ -499,16 +619,16 @@
         hasDigits = true;
       } else {
         if (!hasDigits) {
-          return error(const SourceString("hex digit expected"));
+          return error("hex digit expected");
         }
-        appendByteStringToken(HEXADECIMAL_INFO, asciiString(start, 0));
+        appendSubstringToken(HEXADECIMAL_INFO, start, true);
         return next;
       }
     }
   }
 
   int tokenizeDotsOrNumber(int next) {
-    int start = byteOffset;
+    int start = scanOffset;
     next = advance();
     if (($0 <= next && next <= $9)) {
       return tokenizeFractionPart(next, start);
@@ -538,15 +658,18 @@
       next = advance();
     }
     if (!hasDigit) {
-      appendByteStringToken(INT_INFO, asciiString(start, -1));
+      // Reduce offset, we already advanced to the token past the period.
+      appendSubstringToken(INT_INFO, start, true, -1);
+
+      // TODO(ahe): Wrong offset for the period. Cannot call beginToken because
+      // the scanner already advanced past the period.
       if (identical($PERIOD, next)) {
         return select($PERIOD, PERIOD_PERIOD_PERIOD_INFO, PERIOD_PERIOD_INFO);
       }
-      // TODO(ahe): Wrong offset for the period.
       appendPrecedenceToken(PERIOD_INFO);
-      return bigSwitch(next);
+      return next;
     }
-    appendByteStringToken(DOUBLE_INFO, asciiString(start, 0));
+    appendSubstringToken(DOUBLE_INFO, start, true);
     return next;
   }
 
@@ -560,7 +683,7 @@
         hasDigits = true;
       } else {
         if (!hasDigits) {
-          return error(const SourceString("digit expected"));
+          return error("digit expected");
         }
         return next;
       }
@@ -569,11 +692,12 @@
   }
 
   int tokenizeSlashOrComment(int next) {
+    int start = scanOffset;
     next = advance();
     if (identical($STAR, next)) {
-      return tokenizeMultiLineComment(next);
+      return tokenizeMultiLineComment(next, start);
     } else if (identical($SLASH, next)) {
-      return tokenizeSingleLineComment(next);
+      return tokenizeSingleLineComment(next, start);
     } else if (identical($EQ, next)) {
       appendPrecedenceToken(SLASH_EQ_INFO);
       return advance();
@@ -583,30 +707,41 @@
     }
   }
 
-  int tokenizeSingleLineComment(int next) {
+  int tokenizeSingleLineComment(int next, int start) {
+    bool asciiOnly = true;
     while (true) {
       next = advance();
-      if (identical($LF, next) || identical($CR, next) || identical($EOF, next)) {
-        appendComment();
+      if (next > 127) asciiOnly = false;
+      if (identical($LF, next) ||
+          identical($CR, next) ||
+          identical($EOF, next)) {
+        if (!asciiOnly) handleUnicode(start);
+        appendComment(start, asciiOnly);
         return next;
       }
     }
   }
 
-  int tokenizeMultiLineComment(int next) {
+
+  int tokenizeMultiLineComment(int next, int start) {
+    bool asciiOnlyComment = true; // Track if the entire comment is ASCII.
+    bool asciiOnlyLines = true; // Track ASCII since the last handleUnicode.
+    int unicodeStart = start;
     int nesting = 1;
     next = advance();
     while (true) {
       if (identical($EOF, next)) {
-        // TODO(ahe): Report error.
+        if (!asciiOnlyLines) handleUnicode(unicodeStart);
+        appendStringToken(BAD_INPUT_INFO, "unterminated multi-line comment");
         return next;
       } else if (identical($STAR, next)) {
         next = advance();
         if (identical($SLASH, next)) {
           --nesting;
           if (0 == nesting) {
+            if (!asciiOnlyLines) handleUnicode(unicodeStart);
             next = advance();
-            appendComment();
+            appendComment(start, asciiOnlyComment);
             return next;
           } else {
             next = advance();
@@ -618,16 +753,30 @@
           next = advance();
           ++nesting;
         }
+      } else if (identical(next, $LF)) {
+        if (!asciiOnlyLines) {
+          // Synchronize the string offset in the utf8 scanner.
+          handleUnicode(unicodeStart);
+          asciiOnlyLines = true;
+          unicodeStart = scanOffset;
+        }
+        lineFeedInMultiline();
+        next = advance();
       } else {
+        if (next > 127) {
+          asciiOnlyLines = false;
+          asciiOnlyComment = false;
+        }
         next = advance();
       }
     }
   }
 
   int tokenizeRawStringKeywordOrIdentifier(int next) {
+    // [next] is $r.
     int nextnext = peek();
     if (identical(nextnext, $DQ) || identical(nextnext, $SQ)) {
-      int start = byteOffset;
+      int start = scanOffset;
       next = advance();
       return tokenizeString(next, start, true);
     }
@@ -636,7 +785,7 @@
 
   int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
     KeywordState state = KeywordState.KEYWORD_STATE;
-    int start = byteOffset;
+    int start = scanOffset;
     while (state != null && $a <= next && next <= $z) {
       state = state.next(next);
       next = advance();
@@ -649,17 +798,17 @@
         identical(next, $_) ||
         identical(next, $$)) {
       return tokenizeIdentifier(next, start, allowDollar);
-    } else if (next < 128) {
+    } else {
       appendKeywordToken(state.keyword);
       return next;
-    } else {
-      return tokenizeIdentifier(next, start, allowDollar);
     }
   }
 
+  /**
+   * [allowDollar] can exclude '$', which is not allowed as part of a string
+   * interpolation identifier.
+   */
   int tokenizeIdentifier(int next, int start, bool allowDollar) {
-    bool isAscii = true;
-
     while (true) {
       if (($a <= next && next <= $z) ||
           ($A <= next && next <= $Z) ||
@@ -667,35 +816,21 @@
           identical(next, $_) ||
           (identical(next, $$) && allowDollar)) {
         next = advance();
-      } else if ((next < 128) || (identical(next, $NBSP))) {
+      } else {
         // Identifier ends here.
-        if (start == byteOffset) {
-          return error(const SourceString("expected identifier"));
-        } else if (isAscii) {
-          appendByteStringToken(IDENTIFIER_INFO, asciiString(start, 0));
+        if (start == scanOffset) {
+          return error("expected identifier");
         } else {
-          appendByteStringToken(BAD_INPUT_INFO, utf8String(start, -1));
+          appendSubstringToken(IDENTIFIER_INFO, start, true);
         }
         return next;
-      } else {
-        int nonAsciiStart = byteOffset;
-        do {
-          next = nextByte();
-          if (identical(next, $NBSP)) break;
-        } while (next > 127);
-        String string = utf8String(nonAsciiStart, -1).slowToString();
-        isAscii = false;
-        int byteLength = nonAsciiStart - byteOffset;
-        addToCharOffset(string.length - byteLength);
       }
     }
   }
 
   int tokenizeAt(int next) {
-    int start = byteOffset;
-    next = advance();
     appendPrecedenceToken(AT_INFO);
-    return next;
+    return advance();
   }
 
   int tokenizeString(int next, int start, bool raw) {
@@ -708,7 +843,7 @@
         return tokenizeMultiLineString(quoteChar, start, raw);
       } else {
         // Empty string.
-        appendByteStringToken(STRING_INFO, utf8String(start, -1));
+        appendSubstringToken(STRING_INFO, start, true);
         return next;
       }
     }
@@ -719,56 +854,72 @@
     }
   }
 
-  static bool isHexDigit(int character) {
-    if ($0 <= character && character <= $9) return true;
-    character |= 0x20;
-    return ($a <= character && character <= $f);
-  }
-
+  /**
+   * [next] is the first character after the qoute.
+   * [start] is the scanOffset of the quote.
+   *
+   * The token contains a substring of the source file, including the
+   * string quotes, backslashes for escaping. For interpolated strings,
+   * the parts before and after are separate tokens.
+   *
+   *   "a $b c"
+   *
+   * gives StringToken("a $), StringToken(b) and StringToken( c").
+   */
   int tokenizeSingleLineString(int next, int quoteChar, int start) {
+    bool asciiOnly = true;
     while (!identical(next, quoteChar)) {
       if (identical(next, $BACKSLASH)) {
         next = advance();
       } else if (identical(next, $$)) {
-        next = tokenizeStringInterpolation(start);
-        start = byteOffset;
+        if (!asciiOnly) handleUnicode(start);
+        next = tokenizeStringInterpolation(start, asciiOnly);
+        start = scanOffset;
+        asciiOnly = true;
         continue;
       }
       if (next <= $CR
-          && (identical(next, $LF) || identical(next, $CR) || identical(next, $EOF))) {
-        return error(const SourceString("unterminated string literal"));
+          && (identical(next, $LF) ||
+              identical(next, $CR) ||
+              identical(next, $EOF))) {
+        if (!asciiOnly) handleUnicode(start);
+        return error("unterminated string literal");
       }
+      if (next > 127) asciiOnly = false;
       next = advance();
     }
-    appendByteStringToken(STRING_INFO, utf8String(start, 0));
-    return advance();
+    if (!asciiOnly) handleUnicode(start);
+    // Advance past the quote character.
+    next = advance();
+    appendSubstringToken(STRING_INFO, start, asciiOnly);
+    return next;
   }
 
-  int tokenizeStringInterpolation(int start) {
-    appendByteStringToken(STRING_INFO, utf8String(start, -1));
+  int tokenizeStringInterpolation(int start, bool asciiOnly) {
+    appendSubstringToken(STRING_INFO, start, asciiOnly);
     beginToken(); // $ starts here.
     int next = advance();
     if (identical(next, $OPEN_CURLY_BRACKET)) {
-      return tokenizeInterpolatedExpression(next, start);
+      return tokenizeInterpolatedExpression(next);
     } else {
-      return tokenizeInterpolatedIdentifier(next, start);
+      return tokenizeInterpolatedIdentifier(next);
     }
   }
 
-  int tokenizeInterpolatedExpression(int next, int start) {
-    appendBeginGroup(STRING_INTERPOLATION_INFO, "\${");
+  int tokenizeInterpolatedExpression(int next) {
+    appendBeginGroup(STRING_INTERPOLATION_INFO);
     beginToken(); // The expression starts here.
-    next = advance();
+    next = advance(); // Move past the curly bracket.
     while (!identical(next, $EOF) && !identical(next, $STX)) {
       next = bigSwitch(next);
     }
     if (identical(next, $EOF)) return next;
-    next = advance();
+    next = advance();  // Move past the $STX.
     beginToken(); // The string interpolation suffix starts here.
     return next;
   }
 
-  int tokenizeInterpolatedIdentifier(int next, int start) {
+  int tokenizeInterpolatedIdentifier(int next) {
     appendPrecedenceToken(STRING_INTERPOLATION_IDENTIFIER_INFO);
     beginToken(); // The identifier starts here.
     next = tokenizeKeywordOrIdentifier(next, false);
@@ -777,23 +928,45 @@
   }
 
   int tokenizeSingleLineRawString(int next, int quoteChar, int start) {
-    next = advance();
+    bool asciiOnly = true;
+    next = advance(); // Advance past the quote
     while (next != $EOF) {
       if (identical(next, quoteChar)) {
-        appendByteStringToken(STRING_INFO, utf8String(start, 0));
-        return advance();
+        if (!asciiOnly) handleUnicode(start);
+        next = advance();
+        appendSubstringToken(STRING_INFO, start, asciiOnly);
+        return next;
       } else if (identical(next, $LF) || identical(next, $CR)) {
-        return error(const SourceString("unterminated string literal"));
+        if (!asciiOnly) handleUnicode(start);
+        return error("unterminated string literal");
+      } else if (next > 127) {
+        asciiOnly = false;
       }
       next = advance();
     }
-    return error(const SourceString("unterminated string literal"));
+    if (!asciiOnly) handleUnicode(start);
+    return error("unterminated string literal");
   }
 
   int tokenizeMultiLineRawString(int quoteChar, int start) {
-    int next = advance();
+    bool asciiOnlyString = true;
+    bool asciiOnlyLine = true;
+    int unicodeStart = start;
+    int next = advance(); // Advance past the (last) quote (of three)
     outer: while (!identical(next, $EOF)) {
       while (!identical(next, quoteChar)) {
+        if (identical(next, $LF)) {
+          if (!asciiOnlyLine) {
+            // Synchronize the string offset in the utf8 scanner.
+            handleUnicode(unicodeStart);
+            asciiOnlyLine = true;
+            unicodeStart = scanOffset;
+          }
+          lineFeedInMultiline();
+        } else if (next > 127) {
+          asciiOnlyLine = false;
+          asciiOnlyString = false;
+        }
         next = advance();
         if (identical(next, $EOF)) break outer;
       }
@@ -801,21 +974,31 @@
       if (identical(next, quoteChar)) {
         next = advance();
         if (identical(next, quoteChar)) {
-          appendByteStringToken(STRING_INFO, utf8String(start, 0));
-          return advance();
+          if (!asciiOnlyLine) handleUnicode(unicodeStart);
+          next = advance();
+          appendSubstringToken(STRING_INFO, start, asciiOnlyString);
+          return next;
         }
       }
     }
-    return error(const SourceString("unterminated string literal"));
+    if (!asciiOnlyLine) handleUnicode(unicodeStart);
+    return error("unterminated string literal");
   }
 
   int tokenizeMultiLineString(int quoteChar, int start, bool raw) {
     if (raw) return tokenizeMultiLineRawString(quoteChar, start);
-    int next = advance();
+    bool asciiOnlyString = true;
+    bool asciiOnlyLine = true;
+    int unicodeStart = start;
+    int next = advance(); // Advance past the (last) quote (of three).
     while (!identical(next, $EOF)) {
       if (identical(next, $$)) {
-        next = tokenizeStringInterpolation(start);
-        start = byteOffset;
+        if (!asciiOnlyLine) handleUnicode(unicodeStart);
+        next = tokenizeStringInterpolation(start, asciiOnlyString);
+        start = scanOffset;
+        unicodeStart = start;
+        asciiOnlyString = true; // A new string token is created for the rest.
+        asciiOnlyLine = true;
         continue;
       }
       if (identical(next, quoteChar)) {
@@ -823,8 +1006,10 @@
         if (identical(next, quoteChar)) {
           next = advance();
           if (identical(next, quoteChar)) {
-            appendByteStringToken(STRING_INFO, utf8String(start, 0));
-            return advance();
+            if (!asciiOnlyLine) handleUnicode(unicodeStart);
+            next = advance();
+            appendSubstringToken(STRING_INFO, start, asciiOnlyString);
+            return next;
           }
         }
         continue;
@@ -833,13 +1018,53 @@
         next = advance();
         if (identical(next, $EOF)) break;
       }
+      if (identical(next, $LF)) {
+        if (!asciiOnlyLine) {
+          // Synchronize the string offset in the utf8 scanner.
+          handleUnicode(unicodeStart);
+          asciiOnlyLine = true;
+          unicodeStart = scanOffset;
+        }
+        lineFeedInMultiline();
+      } else if (next > 127) {
+        asciiOnlyString = false;
+        asciiOnlyLine = false;
+      }
       next = advance();
     }
-    return error(const SourceString("unterminated string literal"));
+    if (!asciiOnlyLine) handleUnicode(unicodeStart);
+    return error("unterminated string literal");
   }
 
-  int error(SourceString message) {
-    appendByteStringToken(BAD_INPUT_INFO, message);
+  int error(String message) {
+    appendStringToken(BAD_INPUT_INFO, message);
     return advance(); // Ensure progress.
   }
+
+  void unmatchedBeginGroup(BeginGroupToken begin) {
+    String error = 'unmatched "${begin.stringValue}"';
+    Token close =
+        new StringToken.fromString(
+            BAD_INPUT_INFO, error, begin.charOffset, true);
+
+    // We want to ensure that unmatched BeginGroupTokens are reported
+    // as errors. However, the rest of the parser assume the groups
+    // are well-balanced and will never look at the endGroup
+    // token. This is a nice property that allows us to skip quickly
+    // over correct code. By inserting an additional error token in
+    // the stream, we can keep ignoring endGroup tokens.
+    //
+    // [begin] --next--> [tail]
+    // [begin] --endG--> [close] --next--> [next] --next--> [tail]
+    //
+    // This allows the parser to skip from [begin] via endGroup to [close] and
+    // ignore the [close] token (assuming it's correct), then the error will be
+    // reported when parsing the [next] token.
+
+    Token next = new StringToken.fromString(
+        BAD_INPUT_INFO, error, begin.charOffset, true);
+    begin.endGroup = close;
+    close.next = next;
+    next.next = begin.next;
+  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner_implementation.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner_implementation.dart
deleted file mode 100644
index 1bd8327..0000000
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner_implementation.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2011, 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 scanner_implementation;
-
-import 'scannerlib.dart';
-import '../util/util.dart';
-import '../util/characters.dart';
-
-part 'array_based_scanner.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner_task.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner_task.dart
index 765f49e..869e20e 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scanner_task.dart
@@ -28,7 +28,7 @@
 
   void scanElements(CompilationUnitElement compilationUnit) {
     Script script = compilationUnit.script;
-    Token tokens = new StringScanner(script.text,
+    Token tokens = new Scanner(script.file,
         includeComments: compiler.preserveComments).tokenize();
     if (compiler.preserveComments) {
       tokens = compiler.processAndStripComments(tokens);
@@ -36,9 +36,17 @@
     compiler.dietParser.dietParse(compilationUnit, tokens);
   }
 
+  /**
+   * Returns the tokens for the [source].
+   *
+   * The [StringScanner] implementation works on strings that end with a '0'
+   * value ('\x00'). If [source] does not with '0', the string is copied before
+   * scanning.
+   */
   Token tokenize(String source) {
     return measure(() {
-      return new StringScanner(source, includeComments: false).tokenize();
+      return new StringScanner.fromString(source, includeComments: false)
+          .tokenize();
     });
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart b/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
index 440eb16..9e3815b 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
@@ -4,9 +4,8 @@
 
 library scanner;
 
-import 'dart:collection' show IterableBase;
+import 'dart:collection' show IterableBase, HashSet;
 
-import 'scanner_implementation.dart';
 import '../elements/elements.dart';
 import '../elements/modelx.dart'
     show FunctionElementX,
@@ -22,6 +21,9 @@
 import '../tree/tree.dart';
 import '../util/characters.dart';
 import '../util/util.dart';
+import '../source_file.dart' show SourceFile, Utf8BytesSourceFile;
+import 'dart:convert' show UTF8;
+import 'dart:typed_data' show Uint8List;
 
 part 'class_element_parser.dart';
 part 'keyword.dart';
@@ -31,5 +33,7 @@
 part 'partial_parser.dart';
 part 'scanner.dart';
 part 'scanner_task.dart';
+part 'array_based_scanner.dart';
+part 'utf8_bytes_scanner.dart';
 part 'string_scanner.dart';
 part 'token.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/string_scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/string_scanner.dart
index 6238388..2dd92f9 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/string_scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/string_scanner.dart
@@ -8,48 +8,48 @@
  * Scanner that reads from a String and creates tokens that points to
  * substrings.
  */
-class StringScanner extends ArrayBasedScanner<SourceString> {
-  final String string;
+class StringScanner extends ArrayBasedScanner {
+  /** The file content. */
+  String string;
 
-  StringScanner(String this.string, {bool includeComments: false})
-    : super(includeComments);
+  /** The current offset in [string]. */
+  int scanOffset = -1;
 
-  int nextByte() => charAt(++byteOffset);
-
-  int peek() => charAt(byteOffset + 1);
-
-  int charAt(index)
-      => (string.length > index) ? string.codeUnitAt(index) : $EOF;
-
-  SourceString asciiString(int start, int offset) {
-    return new SourceString.fromSubstring(string, start, byteOffset + offset);
+  StringScanner(SourceFile file, {bool includeComments: false})
+      : string = file.slowText(),
+        super(file, includeComments) {
+    ensureZeroTermination();
   }
 
-  SourceString utf8String(int start, int offset) {
-    return new SourceString.fromSubstring(
-        string, start, byteOffset + offset + 1);
+  StringScanner.fromString(this.string, {bool includeComments: false})
+      : super(null, includeComments) {
+    ensureZeroTermination();
   }
 
-  void appendByteStringToken(PrecedenceInfo info, SourceString value) {
-    // assert(kind != $a || keywords.get(value) == null);
-    tail.next = new StringToken.fromSource(info, value, tokenStart);
+  void ensureZeroTermination() {
+    if (string.isEmpty || string.codeUnitAt(string.length - 1) != 0) {
+      // TODO(lry): abort instead of copying the array, or warn?
+      string = string + '\x00';
+    }
+  }
+
+  int advance() => string.codeUnitAt(++scanOffset);
+  int peek() => string.codeUnitAt(scanOffset + 1);
+
+  int get stringOffset => scanOffset;
+
+  int currentAsUnicode(int next) => next;
+
+  void handleUnicode(int startScanOffset) { }
+
+
+  Token firstToken() => tokens.next;
+  Token previousToken() => tail;
+
+  void appendSubstringToken(PrecedenceInfo info, int start,
+                            bool asciiOnly, [int extraOffset = 0]) {
+    tail.next = new StringToken.fromSubstring(info, string, start,
+        scanOffset + extraOffset, tokenStart, true);
     tail = tail.next;
   }
-
-  void unmatchedBeginGroup(BeginGroupToken begin) {
-    SourceString error = new SourceString('unmatched "${begin.stringValue}"');
-    Token close =
-        new StringToken.fromSource(BAD_INPUT_INFO, error, begin.charOffset);
-    // We want to ensure that unmatched BeginGroupTokens are reported
-    // as errors. However, the rest of the parser assume the groups
-    // are well-balanced and will never look at the endGroup
-    // token. This is a nice property that allows us to skip quickly
-    // over correct code. By inserting an additional error token in
-    // the stream, we can keep ignoring endGroup tokens.
-    Token next =
-        new StringToken.fromSource(BAD_INPUT_INFO, error, begin.charOffset);
-    begin.endGroup = close;
-    close.next = next;
-    next.next = begin.next;
-  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/token.dart b/sdk/lib/_internal/compiler/implementation/scanner/token.dart
index 53a1f08..d9909e3 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/token.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/token.dart
@@ -76,42 +76,57 @@
 const int COMMENT_TOKEN = CARET_EQ_TOKEN + 1;
 const int STRING_INTERPOLATION_IDENTIFIER_TOKEN = COMMENT_TOKEN + 1;
 
-// TODO(ahe): Get rid of this.
-const int UNKNOWN_TOKEN = 1024;
-
 /**
  * A token that doubles as a linked list.
  */
-class Token implements Spannable {
-  /**
-   * The precedence info for this token. [info] determines the kind and the
-   * precedence level of this token.
-   */
-  final PrecedenceInfo info;
-
+abstract class Token implements Spannable {
   /**
    * The character offset of the start of this token within the source text.
    */
   final int charOffset;
 
+  Token(this.charOffset);
+
   /**
    * The next token in the token stream.
    */
   Token next;
 
-  Token(this.info, this.charOffset);
-
-  get value => info.value;
+  /**
+   * The precedence info for this token. [info] determines the kind and the
+   * precedence level of this token.
+   *
+   * Defined as getter to save a field in the [KeywordToken] subclass.
+   */
+  PrecedenceInfo get info;
 
   /**
-   * Returns the string value for keywords and symbols. For instance 'class' for
-   * the [CLASS] keyword token and '*' for a [Token] based on [STAR_INFO]. For
-   * other tokens, such identifiers, strings, numbers, etc, [stringValue]
-   * returns [:null:].
+   * The string represented by this token, a substring of the source code.
    *
-   * [stringValue] should only be used for testing keywords and symbols.
+   * For [StringToken]s the value includes the quotes, explicit escapes, etc.
+   *
    */
-  String get stringValue => info.value.stringValue;
+  String get value;
+
+  /**
+   * For symbol and keyword tokens, returns the string value reprenseted by this
+   * token. For [StringToken]s this method returns [:null:].
+   *
+   * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time
+   * constant originating in the [PrecedenceInfo] or in the [Keyword] instance.
+   * This allows testing for keywords and symbols using [:identical:], e.g.,
+   * [:identical('class', token.value):].
+   *
+   * Note that returning [:null:] for string tokens is important to identify
+   * symbols and keywords, we cannot use [value] instead. The string literal
+   *   "$a($b"
+   * produces ..., SymbolToken($), StringToken(a), StringToken((), ...
+   *
+   * After parsing the identifier 'a', the parser tests for a function
+   * declaration using [:identical(next.stringValue, '('):], which (rihgtfully)
+   * returns false because stringValue returns [:null:].
+   */
+  String get stringValue;
 
   /**
    * The kind enum of this token as determined by its [info].
@@ -123,31 +138,32 @@
    */
   int get precedence => info.precedence;
 
-  bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN);
+  /**
+   * True if this token is an identifier. Some keywords allowed as identifiers,
+   * see implementaiton in [KeywordToken].
+   */
+  bool isIdentifier();
 
   /**
    * Returns a textual representation of this token to be used for debugging
    * purposes. The resulting string might contain information about the
    * structure of the token, for example 'StringToken(foo)' for the identifier
-   * token 'foo'. Use [slowToString] for the text actually parsed by the token.
+   * token 'foo'.
+   *
+   * Use [value] for the text actually parsed by the token.
    */
-  String toString() => info.value.toString();
-
-  /**
-   * The text parsed by this token.
-   */
-  String slowToString() => toString();
+  String toString();
 
   /**
    * The number of characters parsed by this token.
    */
-  int get slowCharCount {
+  int get charCount {
     if (info == BAD_INPUT_INFO) {
       // This is a token that wraps around an error message. Return 1
       // instead of the size of the length of the error message.
       return 1;
     } else {
-      return slowToString().length;
+      return value.length;
     }
   }
 
@@ -155,129 +171,230 @@
 }
 
 /**
- * A keyword token.
+ * A symbol token represents the symbol in its precendence info.
+ * Also used for end of file with EOF_INFO.
  */
-class KeywordToken extends Token {
-  final Keyword value;
-  String get stringValue => value.syntax;
+class SymbolToken extends Token {
 
-  KeywordToken(Keyword value, int charOffset)
-    : this.value = value, super(value.info, charOffset);
+  final PrecedenceInfo info;
 
-  bool isIdentifier() => value.isPseudo || value.isBuiltIn;
+  SymbolToken(this.info, int charOffset) : super(charOffset);
 
-  String toString() => value.syntax;
+  String get value => info.value;
+
+  String get stringValue => info.value;
+
+  bool isIdentifier() => false;
+
+  String toString() => "SymbolToken($value)";
 }
 
 /**
- * A String-valued token.
+ * A [BeginGroupToken] reprsents a symbol that may be the beginning of
+ * a pair of brackets, i.e., ( { [ < or ${
+ * The [endGroup] token points to the matching closing bracked in case
+ * it can be identified during scanning.
+ */
+class BeginGroupToken extends SymbolToken {
+  Token endGroup;
+
+  BeginGroupToken(PrecedenceInfo info, int charOffset)
+    : super(info, charOffset);
+}
+
+/**
+ * A keyword token.
+ */
+class KeywordToken extends Token {
+  final Keyword keyword;
+
+  KeywordToken(this.keyword, int charOffset) : super(charOffset);
+
+  PrecedenceInfo get info => keyword.info;
+
+  String get value => keyword.syntax;
+
+  String get stringValue => keyword.syntax;
+
+  bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn;
+
+  String toString() => "KeywordToken($value)";
+}
+
+/**
+ * A String-valued token. Represents identifiers, string literals,
+ * number literals, comments and error tokens, using the corresponding
+ * precedence info.
  */
 class StringToken extends Token {
-  final SourceString value;
-
-  StringToken(PrecedenceInfo info, String value, int charOffset)
-    : this.fromSource(info, new SourceString(value), charOffset);
-
-  StringToken.fromSource(PrecedenceInfo info, this.value, int charOffset)
-    : super(info, charOffset);
-
-  String toString() => "StringToken(${value.slowToString()})";
-
-  String slowToString() => value.slowToString();
-}
-
-abstract class SourceString extends IterableBase<int> {
-  const factory SourceString(String string) = StringWrapper;
-
-  static final Map<String, StringWrapper> canonicalizedValues =
-      new Map<String, StringWrapper>();
-
-  factory SourceString.fromSubstring(String string, int begin, int end) {
-    var substring = string.substring(begin, end);
-    return canonicalizedValues.putIfAbsent(
-        substring, () => new StringWrapper(substring));
-  }
-
-  void printOn(StringBuffer sb);
-
-  /** Gives a [SourceString] that is not including the [initial] first and
-   * [terminal] last characters. This is only intended to be used to remove
-   * quotes from string literals (including an initial '@' for raw strings).
+  /**
+   * The length threshold above which substring tokens are computed lazily.
+   *
+   * For string tokens that are substrings of the program source, the actual
+   * substring extraction is performed lazily. This is beneficial because
+   * not all scanned code is actually used. For unused parts, the substrings
+   * are never computed and allocated.
    */
-  SourceString copyWithoutQuotes(int initial, int terminal);
+  static const int LAZY_THRESHOLD = 4;
 
-  String get stringValue;
+  var valueOrLazySubstring;
 
-  String slowToString();
+  final PrecedenceInfo info;
 
-  bool get isEmpty;
+  /**
+   * Creates a non-lazy string token. If [canonicalize] is true, the string
+   * is canonicalized before the token is created.
+   */
+  StringToken.fromString(this.info, String value, int charOffset,
+                         [bool canonicalize = false])
+      : valueOrLazySubstring = canonicalizedString(value, canonicalize),
+        super(charOffset);
 
-  bool isPrivate();
-}
-
-class StringWrapper extends IterableBase<int> implements SourceString {
-  final String stringValue;
-
-  const StringWrapper(this.stringValue);
-
-  int get hashCode => stringValue.hashCode;
-
-  bool operator ==(other) {
-    return other is SourceString && toString() == other.slowToString();
+  /**
+   * Creates a lazy string token. If [canonicalize] is true, the string
+   * is canonicalized before the token is created.
+   */
+  StringToken.fromSubstring(this.info, String data, int start, int end,
+                            int charOffset, [bool canonicalize = false])
+      : super(charOffset) {
+    int length = end - start;
+    if (length <= LAZY_THRESHOLD) {
+      valueOrLazySubstring = canonicalizedString(data.substring(start, end),
+                                            canonicalize);
+    } else {
+      valueOrLazySubstring =
+          new LazySubstring(data, start, length, canonicalize);
+    }
   }
 
-  Iterator<int> get iterator => new StringCodeIterator(stringValue);
-
-  void printOn(StringBuffer sb) {
-    sb.write(stringValue);
+  /**
+   * Creates a lazy string token. If [asciiOnly] is false, the byte array
+   * is passed through a UTF-8 decoder.
+   */
+  StringToken.fromUtf8Bytes(this.info, List<int> data, int start, int end,
+                            bool asciiOnly, int charOffset)
+      : super(charOffset) {
+    int length = end - start;
+    if (length <= LAZY_THRESHOLD) {
+      valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly);
+    } else {
+      valueOrLazySubstring = new LazySubstring(data, start, length, asciiOnly);
+    }
   }
 
-  String toString() => stringValue;
-
-  String slowToString() => stringValue;
-
-  SourceString copyWithoutQuotes(int initial, int terminal) {
-    assert(0 <= initial);
-    assert(0 <= terminal);
-    assert(initial + terminal <= stringValue.length);
-    return new StringWrapper(
-        stringValue.substring(initial, stringValue.length - terminal));
+  String get value {
+    if (valueOrLazySubstring is String) {
+      return valueOrLazySubstring;
+    } else {
+      assert(valueOrLazySubstring is LazySubstring);
+      var data = valueOrLazySubstring.data;
+      int start = valueOrLazySubstring.start;
+      int end = start + valueOrLazySubstring.length;
+      if (data is String) {
+        valueOrLazySubstring = canonicalizedString(
+            data.substring(start, end), valueOrLazySubstring.boolValue);
+      } else {
+        valueOrLazySubstring = decodeUtf8(
+            data, start, end, valueOrLazySubstring.boolValue);
+      }
+      return valueOrLazySubstring;
+    }
   }
 
-  bool get isEmpty => stringValue.isEmpty;
+  String get stringValue => null;
 
-  bool isPrivate() => !isEmpty && stringValue.codeUnitAt(0) == $_;
-}
+  bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN);
 
-class StringCodeIterator implements Iterator<int> {
-  final String string;
-  int index;
-  final int end;
-  int _current;
+  String toString() => "StringToken($value)";
 
-  StringCodeIterator(String string) :
-    this.string = string, index = 0, end = string.length;
+  static final HashSet<String> canonicalizedSubstrings =
+      new HashSet();
 
-  StringCodeIterator.substring(this.string, this.index, this.end) {
-    assert(0 <= index);
-    assert(index <= end);
-    assert(end <= string.length);
+  static String canonicalizedString(String s, bool canonicalize) {
+    if (!canonicalize) return s;
+    var result = canonicalizedSubstrings.lookup(s);
+    if (result != null) return result;
+    canonicalizedSubstrings.add(s);
+    return s;
   }
 
-  int get current => _current;
-
-  bool moveNext() {
-    _current = null;
-    if (index >= end) return false;
-    _current = string.codeUnitAt(index++);
-    return true;
+  static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) {
+    var s;
+    if (asciiOnly) {
+      // getRange returns an iterator, it does not copy the data.
+      s = new String.fromCharCodes(data.getRange(start, end));
+    } else {
+      // TODO(lry): this is measurably slow. Also sublist is copied eagerly.
+      var bytes = data.sublist(start, end);
+      s = UTF8.decode(bytes);
+    }
+    return canonicalizedString(s, true);
   }
 }
 
-class BeginGroupToken extends StringToken {
-  Token endGroup;
-  BeginGroupToken(PrecedenceInfo info, String value, int charOffset)
-    : super(info, value, charOffset);
+/**
+ * This class represents the necessary information to compute a substring
+ * lazily. The substring can either originate in a string or in a [:List<int>:]
+ * of UTF-8 bytes.
+ */
+abstract class LazySubstring {
+  /** The original data, either a string or a List<int> */
+  get data;
+
+  int get start;
+  int get length;
+
+  /**
+   * If this substring is based on a String, the boolean indicates wheter the
+   * resulting substring should be canonicalized.
+   *
+   * For substrings based on a byte array, the boolean value is true if the
+   * array only holds ASCII characters. The resulting substring will be
+   * canonicalized after decoding.
+   */
+  bool get boolValue;
+
+  LazySubstring.internal();
+
+  factory LazySubstring(data, int start, int length, bool b) {
+    // See comment on [CompactLazySubstring].
+    if (start < 0x100000 && length < 0x200) {
+      int fields = (start << 9);
+      fields = fields | length;
+      fields = fields << 1;
+      if (b) fields |= 1;
+      return new CompactLazySubstring(data, fields);
+    } else {
+      return new FullLazySubstring(data, start, length, b);
+    }
+  }
+}
+
+/**
+ * This class encodes [start], [length] and [boolValue] in a single
+ * 30 bit integer. It uses 20 bits for [start], which covers source files
+ * of 1M. [length] has 9 bits, which covers 512 characters.
+ *
+ * The file html_dart2js.dart is currently around 1M.
+ */
+class CompactLazySubstring extends LazySubstring {
+  final data;
+  final int fields;
+
+  CompactLazySubstring(this.data, this.fields) : super.internal();
+
+  int get start => fields >> 10;
+  int get length => (fields >> 1) & 0x1ff;
+  bool get boolValue => (fields & 1) == 1;
+}
+
+class FullLazySubstring extends LazySubstring {
+  final data;
+  final int start;
+  final int length;
+  final bool boolValue;
+  FullLazySubstring(this.data, this.start, this.length, this.boolValue)
+      : super.internal();
 }
 
 bool isUserDefinableOperator(String value) {
@@ -315,7 +432,7 @@
 bool isMinusOperator(String value) => identical(value, '-');
 
 class PrecedenceInfo {
-  final SourceString value;
+  final String value;
   final int precedence;
   final int kind;
 
@@ -328,11 +445,11 @@
 
 // TODO(ahe): The following are not tokens in Dart.
 const PrecedenceInfo BACKPING_INFO =
-  const PrecedenceInfo(const SourceString('`'), 0, BACKPING_TOKEN);
+  const PrecedenceInfo('`', 0, BACKPING_TOKEN);
 const PrecedenceInfo BACKSLASH_INFO =
-  const PrecedenceInfo(const SourceString('\\'), 0, BACKSLASH_TOKEN);
+  const PrecedenceInfo('\\', 0, BACKSLASH_TOKEN);
 const PrecedenceInfo PERIOD_PERIOD_PERIOD_INFO =
-  const PrecedenceInfo(const SourceString('...'), 0,
+  const PrecedenceInfo('...', 0,
                        PERIOD_PERIOD_PERIOD_TOKEN);
 
 /**
@@ -341,214 +458,210 @@
  */
 const int CASCADE_PRECEDENCE = 2;
 const PrecedenceInfo PERIOD_PERIOD_INFO =
-  const PrecedenceInfo(const SourceString('..'), CASCADE_PRECEDENCE,
+  const PrecedenceInfo('..', CASCADE_PRECEDENCE,
                        PERIOD_PERIOD_TOKEN);
 
 const PrecedenceInfo BANG_INFO =
-  const PrecedenceInfo(const SourceString('!'), 0, BANG_TOKEN);
+  const PrecedenceInfo('!', 0, BANG_TOKEN);
 const PrecedenceInfo COLON_INFO =
-  const PrecedenceInfo(const SourceString(':'), 0, COLON_TOKEN);
+  const PrecedenceInfo(':', 0, COLON_TOKEN);
 const PrecedenceInfo INDEX_INFO =
-  const PrecedenceInfo(const SourceString('[]'), 0, INDEX_TOKEN);
+  const PrecedenceInfo('[]', 0, INDEX_TOKEN);
 const PrecedenceInfo MINUS_MINUS_INFO =
-  const PrecedenceInfo(const SourceString('--'), POSTFIX_PRECEDENCE,
+  const PrecedenceInfo('--', POSTFIX_PRECEDENCE,
                        MINUS_MINUS_TOKEN);
 const PrecedenceInfo PLUS_PLUS_INFO =
-  const PrecedenceInfo(const SourceString('++'), POSTFIX_PRECEDENCE,
+  const PrecedenceInfo('++', POSTFIX_PRECEDENCE,
                        PLUS_PLUS_TOKEN);
 const PrecedenceInfo TILDE_INFO =
-  const PrecedenceInfo(const SourceString('~'), 0, TILDE_TOKEN);
+  const PrecedenceInfo('~', 0, TILDE_TOKEN);
 
 const PrecedenceInfo FUNCTION_INFO =
-  const PrecedenceInfo(const SourceString('=>'), 0, FUNCTION_TOKEN);
+  const PrecedenceInfo('=>', 0, FUNCTION_TOKEN);
 const PrecedenceInfo HASH_INFO =
-  const PrecedenceInfo(const SourceString('#'), 0, HASH_TOKEN);
+  const PrecedenceInfo('#', 0, HASH_TOKEN);
 const PrecedenceInfo INDEX_EQ_INFO =
-  const PrecedenceInfo(const SourceString('[]='), 0, INDEX_EQ_TOKEN);
+  const PrecedenceInfo('[]=', 0, INDEX_EQ_TOKEN);
 const PrecedenceInfo SEMICOLON_INFO =
-  const PrecedenceInfo(const SourceString(';'), 0, SEMICOLON_TOKEN);
+  const PrecedenceInfo(';', 0, SEMICOLON_TOKEN);
 const PrecedenceInfo COMMA_INFO =
-  const PrecedenceInfo(const SourceString(','), 0, COMMA_TOKEN);
+  const PrecedenceInfo(',', 0, COMMA_TOKEN);
 
 const PrecedenceInfo AT_INFO =
-  const PrecedenceInfo(const SourceString('@'), 0, AT_TOKEN);
+  const PrecedenceInfo('@', 0, AT_TOKEN);
 
 // Assignment operators.
 const int ASSIGNMENT_PRECEDENCE = 1;
 const PrecedenceInfo AMPERSAND_EQ_INFO =
-  const PrecedenceInfo(const SourceString('&='),
+  const PrecedenceInfo('&=',
                        ASSIGNMENT_PRECEDENCE, AMPERSAND_EQ_TOKEN);
 const PrecedenceInfo BAR_EQ_INFO =
-  const PrecedenceInfo(const SourceString('|='),
+  const PrecedenceInfo('|=',
                        ASSIGNMENT_PRECEDENCE, BAR_EQ_TOKEN);
 const PrecedenceInfo CARET_EQ_INFO =
-  const PrecedenceInfo(const SourceString('^='),
+  const PrecedenceInfo('^=',
                        ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN);
 const PrecedenceInfo EQ_INFO =
-  const PrecedenceInfo(const SourceString('='),
+  const PrecedenceInfo('=',
                        ASSIGNMENT_PRECEDENCE, EQ_TOKEN);
 const PrecedenceInfo GT_GT_EQ_INFO =
-  const PrecedenceInfo(const SourceString('>>='),
+  const PrecedenceInfo('>>=',
                        ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN);
 const PrecedenceInfo LT_LT_EQ_INFO =
-  const PrecedenceInfo(const SourceString('<<='),
+  const PrecedenceInfo('<<=',
                        ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN);
 const PrecedenceInfo MINUS_EQ_INFO =
-  const PrecedenceInfo(const SourceString('-='),
+  const PrecedenceInfo('-=',
                        ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN);
 const PrecedenceInfo PERCENT_EQ_INFO =
-  const PrecedenceInfo(const SourceString('%='),
+  const PrecedenceInfo('%=',
                        ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN);
 const PrecedenceInfo PLUS_EQ_INFO =
-  const PrecedenceInfo(const SourceString('+='),
+  const PrecedenceInfo('+=',
                        ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN);
 const PrecedenceInfo SLASH_EQ_INFO =
-  const PrecedenceInfo(const SourceString('/='),
+  const PrecedenceInfo('/=',
                        ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN);
 const PrecedenceInfo STAR_EQ_INFO =
-  const PrecedenceInfo(const SourceString('*='),
+  const PrecedenceInfo('*=',
                        ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN);
 const PrecedenceInfo TILDE_SLASH_EQ_INFO =
-  const PrecedenceInfo(const SourceString('~/='),
+  const PrecedenceInfo('~/=',
                        ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN);
 
 const PrecedenceInfo QUESTION_INFO =
-  const PrecedenceInfo(const SourceString('?'), 3, QUESTION_TOKEN);
+  const PrecedenceInfo('?', 3, QUESTION_TOKEN);
 
 const PrecedenceInfo BAR_BAR_INFO =
-  const PrecedenceInfo(const SourceString('||'), 4, BAR_BAR_TOKEN);
+  const PrecedenceInfo('||', 4, BAR_BAR_TOKEN);
 
 const PrecedenceInfo AMPERSAND_AMPERSAND_INFO =
-  const PrecedenceInfo(const SourceString('&&'), 5, AMPERSAND_AMPERSAND_TOKEN);
+  const PrecedenceInfo('&&', 5, AMPERSAND_AMPERSAND_TOKEN);
 
 const PrecedenceInfo BAR_INFO =
-  const PrecedenceInfo(const SourceString('|'), 8, BAR_TOKEN);
+  const PrecedenceInfo('|', 8, BAR_TOKEN);
 
 const PrecedenceInfo CARET_INFO =
-  const PrecedenceInfo(const SourceString('^'), 9, CARET_TOKEN);
+  const PrecedenceInfo('^', 9, CARET_TOKEN);
 
 const PrecedenceInfo AMPERSAND_INFO =
-  const PrecedenceInfo(const SourceString('&'), 10, AMPERSAND_TOKEN);
+  const PrecedenceInfo('&', 10, AMPERSAND_TOKEN);
 
 // Equality operators.
 const int EQUALITY_PRECEDENCE = 6;
 const PrecedenceInfo BANG_EQ_EQ_INFO =
-  const PrecedenceInfo(const SourceString('!=='),
+  const PrecedenceInfo('!==',
                        EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN);
 const PrecedenceInfo BANG_EQ_INFO =
-  const PrecedenceInfo(const SourceString('!='),
+  const PrecedenceInfo('!=',
                        EQUALITY_PRECEDENCE, BANG_EQ_TOKEN);
 const PrecedenceInfo EQ_EQ_EQ_INFO =
-  const PrecedenceInfo(const SourceString('==='),
+  const PrecedenceInfo('===',
                        EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN);
 const PrecedenceInfo EQ_EQ_INFO =
-  const PrecedenceInfo(const SourceString('=='),
+  const PrecedenceInfo('==',
                        EQUALITY_PRECEDENCE, EQ_EQ_TOKEN);
 
 // Relational operators.
 const int RELATIONAL_PRECEDENCE = 7;
 const PrecedenceInfo GT_EQ_INFO =
-  const PrecedenceInfo(const SourceString('>='),
+  const PrecedenceInfo('>=',
                        RELATIONAL_PRECEDENCE, GT_EQ_TOKEN);
 const PrecedenceInfo GT_INFO =
-  const PrecedenceInfo(const SourceString('>'),
+  const PrecedenceInfo('>',
                        RELATIONAL_PRECEDENCE, GT_TOKEN);
 const PrecedenceInfo IS_INFO =
-  const PrecedenceInfo(const SourceString('is'),
+  const PrecedenceInfo('is',
                        RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
 const PrecedenceInfo AS_INFO =
-  const PrecedenceInfo(const SourceString('as'),
+  const PrecedenceInfo('as',
                        RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
 const PrecedenceInfo LT_EQ_INFO =
-  const PrecedenceInfo(const SourceString('<='),
+  const PrecedenceInfo('<=',
                        RELATIONAL_PRECEDENCE, LT_EQ_TOKEN);
 const PrecedenceInfo LT_INFO =
-  const PrecedenceInfo(const SourceString('<'),
+  const PrecedenceInfo('<',
                        RELATIONAL_PRECEDENCE, LT_TOKEN);
 
 // Shift operators.
 const PrecedenceInfo GT_GT_INFO =
-  const PrecedenceInfo(const SourceString('>>'), 11, GT_GT_TOKEN);
+  const PrecedenceInfo('>>', 11, GT_GT_TOKEN);
 const PrecedenceInfo LT_LT_INFO =
-  const PrecedenceInfo(const SourceString('<<'), 11, LT_LT_TOKEN);
+  const PrecedenceInfo('<<', 11, LT_LT_TOKEN);
 
 // Additive operators.
 const PrecedenceInfo MINUS_INFO =
-  const PrecedenceInfo(const SourceString('-'), 12, MINUS_TOKEN);
+  const PrecedenceInfo('-', 12, MINUS_TOKEN);
 const PrecedenceInfo PLUS_INFO =
-  const PrecedenceInfo(const SourceString('+'), 12, PLUS_TOKEN);
+  const PrecedenceInfo('+', 12, PLUS_TOKEN);
 
 // Multiplicative operators.
 const PrecedenceInfo PERCENT_INFO =
-  const PrecedenceInfo(const SourceString('%'), 13, PERCENT_TOKEN);
+  const PrecedenceInfo('%', 13, PERCENT_TOKEN);
 const PrecedenceInfo SLASH_INFO =
-  const PrecedenceInfo(const SourceString('/'), 13, SLASH_TOKEN);
+  const PrecedenceInfo('/', 13, SLASH_TOKEN);
 const PrecedenceInfo STAR_INFO =
-  const PrecedenceInfo(const SourceString('*'), 13, STAR_TOKEN);
+  const PrecedenceInfo('*', 13, STAR_TOKEN);
 const PrecedenceInfo TILDE_SLASH_INFO =
-  const PrecedenceInfo(const SourceString('~/'), 13, TILDE_SLASH_TOKEN);
+  const PrecedenceInfo('~/', 13, TILDE_SLASH_TOKEN);
 
 const int POSTFIX_PRECEDENCE = 14;
 const PrecedenceInfo PERIOD_INFO =
-  const PrecedenceInfo(const SourceString('.'), POSTFIX_PRECEDENCE,
+  const PrecedenceInfo('.', POSTFIX_PRECEDENCE,
                        PERIOD_TOKEN);
 
 const PrecedenceInfo KEYWORD_INFO =
-  const PrecedenceInfo(const SourceString('keyword'), 0, KEYWORD_TOKEN);
+  const PrecedenceInfo('keyword', 0, KEYWORD_TOKEN);
 
 const PrecedenceInfo EOF_INFO =
-  const PrecedenceInfo(const SourceString('EOF'), 0, EOF_TOKEN);
+  const PrecedenceInfo('EOF', 0, EOF_TOKEN);
 
 const PrecedenceInfo IDENTIFIER_INFO =
-  const PrecedenceInfo(const SourceString('identifier'), 0, IDENTIFIER_TOKEN);
+  const PrecedenceInfo('identifier', 0, IDENTIFIER_TOKEN);
 
 const PrecedenceInfo BAD_INPUT_INFO =
-  const PrecedenceInfo(const SourceString('malformed input'), 0,
+  const PrecedenceInfo('malformed input', 0,
                        BAD_INPUT_TOKEN);
 
 const PrecedenceInfo OPEN_PAREN_INFO =
-  const PrecedenceInfo(const SourceString('('), POSTFIX_PRECEDENCE,
+  const PrecedenceInfo('(', POSTFIX_PRECEDENCE,
                        OPEN_PAREN_TOKEN);
 
 const PrecedenceInfo CLOSE_PAREN_INFO =
-  const PrecedenceInfo(const SourceString(')'), 0, CLOSE_PAREN_TOKEN);
+  const PrecedenceInfo(')', 0, CLOSE_PAREN_TOKEN);
 
 const PrecedenceInfo OPEN_CURLY_BRACKET_INFO =
-  const PrecedenceInfo(const SourceString('{'), 0, OPEN_CURLY_BRACKET_TOKEN);
+  const PrecedenceInfo('{', 0, OPEN_CURLY_BRACKET_TOKEN);
 
 const PrecedenceInfo CLOSE_CURLY_BRACKET_INFO =
-  const PrecedenceInfo(const SourceString('}'), 0, CLOSE_CURLY_BRACKET_TOKEN);
+  const PrecedenceInfo('}', 0, CLOSE_CURLY_BRACKET_TOKEN);
 
 const PrecedenceInfo INT_INFO =
-  const PrecedenceInfo(const SourceString('int'), 0, INT_TOKEN);
+  const PrecedenceInfo('int', 0, INT_TOKEN);
 
 const PrecedenceInfo STRING_INFO =
-  const PrecedenceInfo(const SourceString('string'), 0, STRING_TOKEN);
+  const PrecedenceInfo('string', 0, STRING_TOKEN);
 
 const PrecedenceInfo OPEN_SQUARE_BRACKET_INFO =
-  const PrecedenceInfo(const SourceString('['), POSTFIX_PRECEDENCE,
+  const PrecedenceInfo('[', POSTFIX_PRECEDENCE,
                        OPEN_SQUARE_BRACKET_TOKEN);
 
 const PrecedenceInfo CLOSE_SQUARE_BRACKET_INFO =
-  const PrecedenceInfo(const SourceString(']'), 0, CLOSE_SQUARE_BRACKET_TOKEN);
+  const PrecedenceInfo(']', 0, CLOSE_SQUARE_BRACKET_TOKEN);
 
 const PrecedenceInfo DOUBLE_INFO =
-  const PrecedenceInfo(const SourceString('double'), 0, DOUBLE_TOKEN);
+  const PrecedenceInfo('double', 0, DOUBLE_TOKEN);
 
 const PrecedenceInfo STRING_INTERPOLATION_INFO =
-  const PrecedenceInfo(const SourceString('\${'), 0,
+  const PrecedenceInfo('\${', 0,
                        STRING_INTERPOLATION_TOKEN);
 
 const PrecedenceInfo STRING_INTERPOLATION_IDENTIFIER_INFO =
-  const PrecedenceInfo(const SourceString('\$'), 0,
+  const PrecedenceInfo('\$', 0,
                        STRING_INTERPOLATION_IDENTIFIER_TOKEN);
 
 const PrecedenceInfo HEXADECIMAL_INFO =
-  const PrecedenceInfo(const SourceString('hexadecimal'), 0, HEXADECIMAL_TOKEN);
+  const PrecedenceInfo('hexadecimal', 0, HEXADECIMAL_TOKEN);
 
 const PrecedenceInfo COMMENT_INFO =
-  const PrecedenceInfo(const SourceString('comment'), 0, COMMENT_TOKEN);
-
-// For reporting lexical errors.
-const PrecedenceInfo ERROR_INFO =
-  const PrecedenceInfo(const SourceString('?'), 0, UNKNOWN_TOKEN);
+  const PrecedenceInfo('comment', 0, COMMENT_TOKEN);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/utf8_bytes_scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/utf8_bytes_scanner.dart
new file mode 100644
index 0000000..7e7cdf713
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/scanner/utf8_bytes_scanner.dart
@@ -0,0 +1,194 @@
+// Copyright (c) 2011, 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 scanner;
+
+/**
+ * Scanner that reads from a UTF-8 encoded list of bytes and creates tokens
+ * that points to substrings.
+ */
+class Utf8BytesScanner extends ArrayBasedScanner {
+  /** The file content. */
+  List<int> bytes;
+
+  /**
+   * Points to the offset of the byte last returned by [advance].
+   *
+   * After invoking [currentAsUnicode], the [byteOffset] points to the last
+   * byte that is part of the (unicode or ASCII) character. That way, [advance]
+   * can always increase the byte offset by 1.
+   */
+  int byteOffset = -1;
+
+  /**
+   * The getter [scanOffset] is expected to return the index where the current
+   * character *starts*. In case of a non-ascii character, after invoking
+   * [currentAsUnicode], the byte offset points to the *last* byte.
+   *
+   * This field keeps track of the number of bytes for the current unicode
+   * character. For example, if bytes 7,8,9 encode one unicode character, the
+   * [byteOffset] is 9 (after invoking [currentAsUnicode]). The [scanSlack]
+   * will be 2, so that [scanOffset] returns 7.
+   */
+  int scanSlack = 0;
+
+  /**
+   * Holds the [byteOffset] value for which the current [scanSlack] is valid.
+   */
+  int scanSlackOffset = -1;
+
+  /**
+   * Returns the byte offset of the first byte that belongs to the current
+   * character.
+   */
+  int get scanOffset {
+    if (byteOffset == scanSlackOffset) {
+      return byteOffset - scanSlack;
+    } else {
+      return byteOffset;
+    }
+  }
+
+  /**
+   * The difference between the number of bytes and the number of corresponding
+   * string characters, up to the current [byteOffset].
+   */
+  int utf8Slack = 0;
+
+  /**
+   * Creates a new Utf8BytesScanner. The source file is expected to be a
+   * [Utf8BytesSourceFile] that holds a list of UTF-8 bytes. Otherwise the
+   * string text of the source file is decoded.
+   *
+   * The list of UTF-8 bytes [file.slowUtf8Bytes()] is expected to return an
+   * array whose last element is '0' to signal the end of the file. If this
+   * is not the case, the entire array is copied before scanning.
+   */
+  Utf8BytesScanner(SourceFile file, {bool includeComments: false})
+      : bytes = file.slowUtf8Bytes(),
+        super(file, includeComments) {
+    ensureZeroTermination();
+  }
+
+  /**
+   * Creates a new Utf8BytesScanner from a list of UTF-8 bytes.
+   *
+   * The last element of the list is expected to be '0' to signal the end of
+   * the file. If this is not the case, the entire array is copied before
+   * scanning.
+   */
+  Utf8BytesScanner.fromBytes(this.bytes, {bool includeComments: false})
+      : super(null, includeComments) {
+    ensureZeroTermination();
+  }
+
+  void ensureZeroTermination() {
+    if (bytes.isEmpty || bytes[bytes.length - 1] != 0) {
+      // TODO(lry): abort instead of copying the array, or warn?
+      var newBytes =  new Uint8List(bytes.length + 1);
+      for (int i = 0; i < bytes.length; i++) {
+        newBytes[i] = bytes[i];
+      }
+      newBytes[bytes.length] = 0;
+      bytes = newBytes;
+    }
+  }
+
+  int advance() => bytes[++byteOffset];
+
+  int peek() => bytes[byteOffset + 1];
+
+  /**
+   * Returns the unicode code point starting at the byte offset [startOffset]
+   * with the byte [nextByte]. If [advance] is true the current [byteOffset]
+   * is advanced to the last byte of the code point.
+   */
+  int nextCodePoint(int startOffset, int nextByte, bool advance) {
+    // The number of 1s in the first byte indicate the number of bytes, at
+    // least 2.
+    int numBytes = 2;
+    int bit = 0x20;
+    while ((nextByte & bit) != 0) {
+      numBytes++;
+      bit >>= 1;
+    }
+    int end = startOffset + numBytes;
+    if (advance) {
+      byteOffset = end - 1;
+    }
+    // TODO(lry): measurably slow, decode creates first a Utf8Decoder and a
+    // _Utf8Decoder instance. Also the sublist is eagerly allocated.
+    String codePoint = UTF8.decode(bytes.sublist(startOffset, end));
+    if (codePoint.length == 1) {
+      if (advance) {
+        utf8Slack += (numBytes - 1);
+        scanSlack = numBytes - 1;
+        scanSlackOffset = byteOffset;
+      }
+      return codePoint.codeUnitAt(0);
+    } else if (codePoint.length == 2) {
+      if (advance) {
+        utf8Slack += (numBytes - 2);
+        scanSlack = numBytes - 1;
+        scanSlackOffset = byteOffset;
+        stringOffsetSlackOffset = byteOffset;
+      }
+      // In case of a surrogate pair, return a single code point.
+      return codePoint.runes.single;
+    } else {
+      throw "Invalid UTF-8 byte sequence: ${bytes.sublist(startOffset, end)}";
+    }
+  }
+
+  int lastUnicodeOffset = -1;
+  int currentAsUnicode(int next) {
+    if (next < 128) return next;
+    // Check if currentAsUnicode was already invoked.
+    if (byteOffset == lastUnicodeOffset) return next;
+    int res = nextCodePoint(byteOffset, next, true);
+    lastUnicodeOffset = byteOffset;
+    return res;
+  }
+
+  void handleUnicode(int startScanOffset) {
+    int end = byteOffset;
+    // TODO(lry): this measurably slows down the scanner for files with unicode.
+    String s = UTF8.decode(bytes.sublist(startScanOffset, end));
+    utf8Slack += (end - startScanOffset) - s.length;
+  }
+
+  /**
+   * This field remembers the byte offset of the last character decoded with
+   * [nextCodePoint] that used two code units in UTF-16.
+   *
+   * [nextCodePoint] returns a single code point for each unicode character,
+   * even if it needs two code units in UTF-16.
+   *
+   * For example, '\u{1d11e}' uses 4 bytes in UTF-8, and two code units in
+   * UTF-16. The [utf8Slack] is therefore 2. After invoking [nextCodePoint], the
+   * [byteOffset] points to the last (of 4) bytes. The [stringOffset] should
+   * return the offset of the first one, which is one position more left than
+   * the [utf8Slack].
+   */
+  int stringOffsetSlackOffset = -1;
+
+  int get stringOffset {
+    if (stringOffsetSlackOffset == byteOffset) {
+      return byteOffset - utf8Slack - 1;
+    } else {
+      return byteOffset - utf8Slack;
+    }
+  }
+
+  Token firstToken() => tokens.next;
+  Token previousToken() => tail;
+
+
+  void appendSubstringToken(PrecedenceInfo info, int start, bool asciiOnly,
+                            [int extraOffset = 0]) {
+    tail.next = new StringToken.fromUtf8Bytes(
+        info, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
+    tail = tail.next;
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/script.dart b/sdk/lib/_internal/compiler/implementation/script.dart
index f6cda01..396f4bd 100644
--- a/sdk/lib/_internal/compiler/implementation/script.dart
+++ b/sdk/lib/_internal/compiler/implementation/script.dart
@@ -16,6 +16,6 @@
 
   Script(this.uri, this.file);
 
-  String get text => (file == null) ? null : file.text;
+  String get text => (file == null) ? null : file.slowText();
   String get name => (file == null) ? null : file.filename;
 }
diff --git a/sdk/lib/_internal/compiler/implementation/source_file.dart b/sdk/lib/_internal/compiler/implementation/source_file.dart
index 3e7d2b8..25f2afb 100644
--- a/sdk/lib/_internal/compiler/implementation/source_file.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_file.dart
@@ -5,42 +5,83 @@
 library source_file;
 
 import 'dart:math';
+import 'dart:convert' show UTF8;
 
 /**
- * Represents a file of source code.
+ * Represents a file of source code. The content can be either a [String] or
+ * a UTF-8 encoded [List<int>] of bytes.
  */
-class SourceFile {
+abstract class SourceFile {
 
   /** The name of the file. */
   final String filename;
 
-  /** The text content of the file. */
-  final String text;
+  SourceFile(this.filename);
 
-  List<int> _lineStarts;
+  /** The text content of the file represented as a String. */
+  String slowText();
 
-  SourceFile(this.filename, this.text);
+  /** The content of the file represented as a UTF-8 encoded [List<int>]. */
+  List<int> slowUtf8Bytes();
 
+  /**
+   * The length of the string representation of this source file, i.e.,
+   * equivalent to [:slowText().length:], but faster.
+   */
+  int get length;
+
+  /**
+   * Sets the string length of this source file. For source files based on UTF-8
+   * byte arrays, the string length is computed and assigned by the scanner.
+   */
+  set length(v);
+
+  /**
+   * A map from line numbers to offsets in the string text representation of
+   * this source file.
+   */
   List<int> get lineStarts {
-    if (_lineStarts == null) {
-      var starts = [0];
-      var index = 0;
-      while (index < text.length) {
-        index = text.indexOf('\n', index) + 1;
-        if (index <= 0) break;
-        starts.add(index);
-      }
-      starts.add(text.length + 1);
-      _lineStarts = starts;
+    if (lineStartsCache == null) {
+      // When reporting errors during scanning, the line numbers are not yet
+      // available and need to be computed using this slow path.
+      lineStartsCache = lineStartsFromString(slowText());
     }
-    return _lineStarts;
+    return lineStartsCache;
   }
 
+  /**
+   * Sets the line numbers map for this source file. This map is computed and
+   * assigned by the scanner, avoiding a separate traversal of the source file.
+   *
+   * The map contains one additional entry at the end of the file, as if the
+   * source file had one more empty line at the end. This simplifies the binary
+   * search in [getLine].
+   */
+  set lineStarts(v) => lineStartsCache = v;
+
+  List<int> lineStartsCache;
+
+  List<int> lineStartsFromString(String text) {
+    var starts = [0];
+    var index = 0;
+    while (index < text.length) {
+      index = text.indexOf('\n', index) + 1;
+      if (index <= 0) break;
+      starts.add(index);
+    }
+    starts.add(text.length + 1); // One additional line start at the end.
+    return starts;
+  }
+
+  /**
+   * Returns the line number for the offset [position] in the string
+   * representation of this source file.
+   */
   int getLine(int position) {
     List<int> starts = lineStarts;
     if (position < 0 || starts.last <= position) {
       throw 'bad position #$position in file $filename with '
-            'length ${text.length}.';
+            'length ${length}.';
     }
     int first = 0;
     int count = starts.length;
@@ -58,10 +99,16 @@
     return first;
   }
 
+  /**
+   * Returns the column number for the offset [position] in the string
+   * representation of this source file.
+   */
   int getColumn(int line, int position) {
     return position - lineStarts[line];
   }
 
+  String slowSubstring(int start, int end);
+
   /**
    * Create a pretty string representation from a character position
    * in the file.
@@ -75,12 +122,12 @@
         '${filename}:${line + 1}:${column + 1}: $message');
     if (includeText) {
       buf.write('\n');
-      var textLine;
+      String textLine;
       // +1 for 0-indexing, +1 again to avoid the last line of the file
-      if ((line + 2) < _lineStarts.length) {
-        textLine = text.substring(_lineStarts[line], _lineStarts[line+1]);
+      if ((line + 2) < lineStarts.length) {
+        textLine = slowSubstring(lineStarts[line], lineStarts[line+1]);
       } else {
-        textLine = '${text.substring(_lineStarts[line])}\n';
+        textLine = '${slowSubstring(lineStarts[line], length)}\n';
       }
 
       int toColumn = min(column + (end-start), textLine.length);
@@ -101,3 +148,47 @@
     return buf.toString();
   }
 }
+
+class Utf8BytesSourceFile extends SourceFile {
+
+  /** The UTF-8 encoded content of the source file. */
+  final List<int> content;
+
+  Utf8BytesSourceFile(String filename, this.content) : super(filename);
+
+  String slowText() => UTF8.decode(content);
+
+  List<int> slowUtf8Bytes() => content;
+
+  String slowSubstring(int start, int end) {
+    // TODO(lry): to make this faster, the scanner could record the UTF-8 slack
+    // for all positions of the source text. We could use [:content.sublist:].
+    return slowText().substring(start, end);
+  }
+
+  int get length {
+    if (lengthCache == -1) {
+      // During scanning the length is not yet assigned, so we use a slow path.
+      length = slowText().length;
+    }
+    return lengthCache;
+  }
+  set length(v) => lengthCache = v;
+  int lengthCache = -1;
+}
+
+class StringSourceFile extends SourceFile {
+
+  final String text;
+
+  StringSourceFile(String filename, this.text) : super(filename);
+
+  int get length => text.length;
+  set length(v) { }
+
+  String slowText() => text;
+
+  List<int> slowUtf8Bytes() => UTF8.encode(text);
+
+  String slowSubstring(int start, int end) => text.substring(start, end);
+}
diff --git a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
index 352f03c..d1ae322 100644
--- a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
@@ -14,27 +14,33 @@
 import 'source_file.dart';
 import 'filenames.dart';
 import 'util/uri_extras.dart';
+import 'dart:typed_data';
 
-String readAll(String filename) {
+List<int> readAll(String filename) {
   var file = (new File(filename)).openSync();
   var length = file.lengthSync();
-  var buffer = new List<int>(length);
+  // +1 to have a 0 terminated list, see [Scanner].
+  var buffer = new Uint8List(length + 1);
   var bytes = file.readIntoSync(buffer, 0, length);
   file.closeSync();
-  return UTF8.decode(buffer);
+  return buffer;
 }
 
-class SourceFileProvider {
+abstract class SourceFileProvider {
   bool isWindows = (Platform.operatingSystem == 'windows');
   Uri cwd = currentDirectory;
   Map<String, SourceFile> sourceFiles = <String, SourceFile>{};
   int dartCharactersRead = 0;
 
   Future<String> readStringFromUri(Uri resourceUri) {
+    return readUtf8BytesFromUri(resourceUri).then(UTF8.decode);
+  }
+
+  Future<List<int>> readUtf8BytesFromUri(Uri resourceUri) {
     if (resourceUri.scheme != 'file') {
       throw new ArgumentError("Unknown scheme in uri '$resourceUri'");
     }
-    String source;
+    List<int> source;
     try {
       source = readAll(uriPathToNative(resourceUri.path));
     } on FileException catch (ex) {
@@ -43,12 +49,16 @@
           "(${ex.osError})");
     }
     dartCharactersRead += source.length;
-    sourceFiles[resourceUri.toString()] = new SourceFile(
+    sourceFiles[resourceUri.toString()] = new Utf8BytesSourceFile(
         relativize(cwd, resourceUri, isWindows), source);
     return new Future.value(source);
   }
 
-  Future<String> call(Uri resourceUri) => readStringFromUri(resourceUri);
+  Future/*<List<int> | String>*/ call(Uri resourceUri);
+}
+
+class CompilerSourceFileProvider extends SourceFileProvider {
+  Future<List<int>> call(Uri resourceUri) => readUtf8BytesFromUri(resourceUri);
 }
 
 class FormattingDiagnosticHandler {
@@ -67,7 +77,7 @@
 
   FormattingDiagnosticHandler([SourceFileProvider provider])
       : this.provider =
-          (provider == null) ? new SourceFileProvider() : provider;
+          (provider == null) ? new CompilerSourceFileProvider() : provider;
 
   void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) {
     if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return;
diff --git a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
index dd07af6..1665d22 100644
--- a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
@@ -192,9 +192,9 @@
   int getColumn() => sourceFile.getColumn(getLine(), token.charOffset);
 
   String getSourceName() {
-    if (token.isIdentifier()) return token.slowToString();
+    if (token.isIdentifier()) return token.value;
     return null;
   }
 
-  bool isValid() => token.charOffset < sourceFile.text.length;
+  bool isValid() => token.charOffset < sourceFile.length;
 }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index d0f2f48..6cd0139 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -11,7 +11,7 @@
  */
 class InterceptedElement extends ElementX {
   final DartType type;
-  InterceptedElement(this.type, SourceString name, Element enclosing)
+  InterceptedElement(this.type, String name, Element enclosing)
       : super(name, ElementKind.PARAMETER, enclosing);
 
   DartType computeType(Compiler compiler) => type;
@@ -67,14 +67,14 @@
         if (compiler.tracer.enabled) {
           String name;
           if (element.isMember()) {
-            String className = element.getEnclosingClass().name.slowToString();
-            String memberName = element.name.slowToString();
+            String className = element.getEnclosingClass().name;
+            String memberName = element.name;
             name = "$className.$memberName";
             if (element.isGenerativeConstructorBody()) {
               name = "$name (body)";
             }
           } else {
-            name = "${element.name.slowToString()}";
+            name = "${element.name}";
           }
           compiler.tracer.traceCompilation(
               name, work.compilationContext, compiler);
@@ -278,9 +278,7 @@
         && Elements.isNativeOrExtendsNative(cls);
     if (backend.isInterceptedMethod(element)) {
       bool isInterceptorClass = backend.isInterceptorClass(cls.declaration);
-      SourceString name = isInterceptorClass
-          ? const SourceString('receiver')
-          : const SourceString('_');
+      String name = isInterceptorClass ? 'receiver' : '_';
       Element parameter = new InterceptedElement(
           cls.computeType(compiler), name, element);
       HParameterValue value = new HParameterValue(parameter);
@@ -295,7 +293,7 @@
     } else if (isNativeUpgradeFactory) {
       bool isInterceptorClass = backend.isInterceptorClass(cls.declaration);
       Element parameter = new InterceptedElement(
-          cls.computeType(compiler), const SourceString('receiver'), element);
+          cls.computeType(compiler), 'receiver', element);
       HParameterValue value = new HParameterValue(parameter);
       builder.graph.explicitReceiverParameter = value;
       builder.graph.entry.addAtEntry(value);
@@ -1034,11 +1032,11 @@
     assert(!function.modifiers.isExternal());
     assert(elements[function] != null);
     openFunction(functionElement, function);
-    SourceString name = functionElement.name;
+    String name = functionElement.name;
     // If [functionElement] is `operator==` we explicitely add a null check at
     // the beginning of the method. This is to avoid having call sites do the
     // null check.
-    if (name == const SourceString('==')) {
+    if (name == '==') {
       if (!backend.operatorEqHandlesNullArgument(functionElement)) {
         handleIf(
             function,
@@ -1209,7 +1207,7 @@
     assert(argumentIndex == compiledArguments.length);
 
     // TODO(kasperl): Bad smell. We shouldn't be constructing elements here.
-    returnElement = new ElementX(const SourceString("result"),
+    returnElement = new ElementX("result",
                                  ElementKind.VARIABLE,
                                  function);
     newLocalsHandler.updateLocal(returnElement,
@@ -1276,7 +1274,7 @@
       }
 
       // Don't inline operator== methods if the parameter can be null.
-      if (element.name == const SourceString('==')) {
+      if (element.name == '==') {
         if (element.getEnclosingClass() != compiler.objectClass
             && providedArguments[1].canBeNull()) {
           return false;
@@ -2037,7 +2035,7 @@
       throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message(
           {'offset': token.charOffset,
            'fileName': sourceFile.filename,
-           'length': sourceFile.text.length});
+           'length': sourceFile.length});
     }
     return location;
   }
@@ -2615,7 +2613,7 @@
     branchBuilder.handleLogicalAndOrWithLeftNode(
         node.receiver,
         () { visit(node.argumentsNode); },
-        isAnd: (const SourceString("&&") == op.source));
+        isAnd: ("&&" == op.source));
   }
 
   void visitLogicalNot(Send node) {
@@ -2650,7 +2648,7 @@
                    HInstruction right,
                    Selector selector,
                    Send send) {
-    switch (op.source.stringValue) {
+    switch (op.source) {
       case "===":
         pushWithPosition(new HIdentity(left, right), op);
         return;
@@ -2662,7 +2660,7 @@
     }
 
     pushInvokeDynamic(send, selector, [left, right], location: op);
-    if (op.source.stringValue == '!=') {
+    if (op.source == '!=') {
       pushWithPosition(new HNot(popBoolified()), op);
     }
   }
@@ -2677,7 +2675,7 @@
   }
 
   String getTargetName(ErroneousElement error, [String prefix]) {
-    String result = error.name.slowToString();
+    String result = error.name;
     if (prefix != null) {
       result = '$prefix $result';
     }
@@ -2846,7 +2844,7 @@
       bool first = true;
       List<String> templates = <String>[];
       for (DartType argument in interface.typeArguments) {
-        templates.add(rti.getTypeRepresentation(argument, (variable) {
+        templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) {
           HInstruction runtimeType = addTypeVariableReference(variable);
           inputs.add(runtimeType);
         }));
@@ -2861,18 +2859,18 @@
 
   visitOperatorSend(Send node) {
     Operator op = node.selector;
-    if (const SourceString("[]") == op.source) {
+    if ("[]" == op.source) {
       visitDynamicSend(node);
-    } else if (const SourceString("&&") == op.source ||
-               const SourceString("||") == op.source) {
+    } else if ("&&" == op.source ||
+               "||" == op.source) {
       visitLogicalAndOr(node, op);
-    } else if (const SourceString("!") == op.source) {
+    } else if ("!" == op.source) {
       visitLogicalNot(node);
     } else if (node.argumentsNode is Prefix) {
       visitUnary(node, op);
-    } else if (const SourceString("is") == op.source) {
+    } else if ("is" == op.source) {
       visitIsSend(node);
-    } else if (const SourceString("as") == op.source) {
+    } else if ("as" == op.source) {
       visit(node.receiver);
       HInstruction expression = pop();
       Node argument = node.arguments.head;
@@ -3009,9 +3007,9 @@
       }
 
       // Visit named arguments and add them into a temporary map.
-      Map<SourceString, HInstruction> instructions =
-          new Map<SourceString, HInstruction>();
-      List<SourceString> namedArguments = selector.namedArguments;
+      Map<String, HInstruction> instructions =
+          new Map<String, HInstruction>();
+      List<String> namedArguments = selector.namedArguments;
       int nameIndex = 0;
       for (; !arguments.isEmpty; arguments = arguments.tail) {
         visit(arguments.head);
@@ -3021,8 +3019,8 @@
       // Iterate through the named arguments to add them to the list
       // of instructions, in an order that can be shared with
       // selectors with the same named arguments.
-      List<SourceString> orderedNames = selector.getOrderedNamedArguments();
-      for (SourceString name in orderedNames) {
+      List<String> orderedNames = selector.getOrderedNamedArguments();
+      for (String name in orderedNames) {
         list.add(instructions[name]);
       }
     }
@@ -3139,8 +3137,7 @@
       // Call a helper method from the isolate library. The isolate
       // library uses its own isolate structure, that encapsulates
       // Leg's isolate.
-      Element element = compiler.isolateHelperLibrary.find(
-          const SourceString('_currentIsolate'));
+      Element element = compiler.isolateHelperLibrary.find('_currentIsolate');
       if (element == null) {
         compiler.cancel(
             'Isolate library and compiler mismatch', node: node);
@@ -3192,8 +3189,7 @@
       push(new HInvokeClosure(selector, <HInstruction>[pop()]));
     } else {
       // Call a helper method from the isolate library.
-      Element element = compiler.isolateHelperLibrary.find(
-          const SourceString('_callInIsolate'));
+      Element element = compiler.isolateHelperLibrary.find('_callInIsolate');
       if (element == null) {
         compiler.cancel(
             'Isolate library and compiler mismatch', node: node);
@@ -3288,67 +3284,67 @@
 
   visitForeignSend(Send node) {
     Selector selector = elements.getSelector(node);
-    SourceString name = selector.name;
-    if (name == const SourceString('JS')) {
+    String name = selector.name;
+    if (name == 'JS') {
       handleForeignJs(node);
-    } else if (name == const SourceString('JS_CURRENT_ISOLATE_CONTEXT')) {
+    } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
       handleForeignJsCurrentIsolateContext(node);
-    } else if (name == const SourceString('JS_CALL_IN_ISOLATE')) {
+    } else if (name == 'JS_CALL_IN_ISOLATE') {
       handleForeignJsCallInIsolate(node);
-    } else if (name == const SourceString('DART_CLOSURE_TO_JS')) {
+    } else if (name == 'DART_CLOSURE_TO_JS') {
       handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS');
-    } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) {
+    } else if (name == 'RAW_DART_FUNCTION_REF') {
       handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF');
-    } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) {
+    } else if (name == 'JS_SET_CURRENT_ISOLATE') {
       handleForeignSetCurrentIsolate(node);
-    } else if (name == const SourceString('JS_CREATE_ISOLATE')) {
+    } else if (name == 'JS_CREATE_ISOLATE') {
       handleForeignCreateIsolate(node);
-    } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) {
+    } else if (name == 'JS_OPERATOR_IS_PREFIX') {
       stack.add(addConstantString(node, backend.namer.operatorIsPrefix()));
-    } else if (name == const SourceString('JS_OBJECT_CLASS_NAME')) {
+    } else if (name == 'JS_OBJECT_CLASS_NAME') {
       String name = backend.namer.getRuntimeTypeName(compiler.objectClass);
       stack.add(addConstantString(node, name));
-    } else if (name == const SourceString('JS_NULL_CLASS_NAME')) {
+    } else if (name == 'JS_NULL_CLASS_NAME') {
       String name = backend.namer.getRuntimeTypeName(compiler.nullClass);
       stack.add(addConstantString(node, name));
-    } else if (name == const SourceString('JS_FUNCTION_CLASS_NAME')) {
+    } else if (name == 'JS_FUNCTION_CLASS_NAME') {
       String name = backend.namer.getRuntimeTypeName(compiler.functionClass);
       stack.add(addConstantString(node, name));
-    } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) {
+    } else if (name == 'JS_OPERATOR_AS_PREFIX') {
       stack.add(addConstantString(node, backend.namer.operatorAsPrefix()));
-    } else if (name == const SourceString('JS_SIGNATURE_NAME')) {
+    } else if (name == 'JS_SIGNATURE_NAME') {
       stack.add(addConstantString(node, backend.namer.operatorSignature()));
-    } else if (name == const SourceString('JS_FUNCTION_TYPE_TAG')) {
+    } else if (name == 'JS_FUNCTION_TYPE_TAG') {
       stack.add(addConstantString(node, backend.namer.functionTypeTag()));
-    } else if (name == const SourceString('JS_FUNCTION_TYPE_VOID_RETURN_TAG')) {
+    } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') {
       stack.add(addConstantString(node,
                                   backend.namer.functionTypeVoidReturnTag()));
-    } else if (name == const SourceString('JS_FUNCTION_TYPE_RETURN_TYPE_TAG')) {
+    } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') {
       stack.add(addConstantString(node,
                                   backend.namer.functionTypeReturnTypeTag()));
     } else if (name ==
-               const SourceString('JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG')) {
+               'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') {
       stack.add(addConstantString(node,
           backend.namer.functionTypeRequiredParametersTag()));
     } else if (name ==
-               const SourceString('JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG')) {
+               'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') {
       stack.add(addConstantString(node,
           backend.namer.functionTypeOptionalParametersTag()));
     } else if (name ==
-               const SourceString('JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG')) {
+               'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') {
       stack.add(addConstantString(node,
           backend.namer.functionTypeNamedParametersTag()));
-    } else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) {
+    } else if (name == 'JS_DART_OBJECT_CONSTRUCTOR') {
       handleForeignDartObjectJsConstructorFunction(node);
-    } else if (name == const SourceString('JS_IS_INDEXABLE_FIELD_NAME')) {
+    } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') {
       Element element = compiler.findHelper(
-          const SourceString('JavaScriptIndexingBehavior'));
+          'JavaScriptIndexingBehavior');
       stack.add(addConstantString(node, backend.namer.operatorIs(element)));
-    } else if (name == const SourceString('JS_CURRENT_ISOLATE')) {
+    } else if (name == 'JS_CURRENT_ISOLATE') {
       handleForeignJsCurrentIsolate(node);
-    } else if (name == const SourceString('JS_GET_NAME')) {
+    } else if (name == 'JS_GET_NAME') {
       handleForeignJsGetName(node);
-    } else if (name == const SourceString('JS_EFFECT')) {
+    } else if (name == 'JS_EFFECT') {
       stack.add(graph.addConstantNull(compiler));
     } else {
       throw "Unknown foreign: ${selector}";
@@ -3358,7 +3354,7 @@
   generateSuperNoSuchMethodSend(Send node,
                                 Selector selector,
                                 List<HInstruction> arguments) {
-    SourceString name = selector.name;
+    String name = selector.name;
 
     ClassElement cls = currentNonClosureClass;
     Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD);
@@ -3369,7 +3365,7 @@
       // [JSInvocationMirror._invokeOn].
       compiler.enqueuer.codegen.registerSelectorUse(selector);
     }
-    String publicName = name.slowToString();
+    String publicName = name;
     if (selector.isSetter()) publicName += '=';
 
     Constant nameConstant = constantSystem.createString(
@@ -3384,10 +3380,10 @@
     add(argumentsInstruction);
 
     var argumentNames = new List<HInstruction>();
-    for (SourceString argumentName in selector.namedArguments) {
+    for (String argumentName in selector.namedArguments) {
       Constant argumentNameConstant =
-          constantSystem.createString(new DartString.literal(
-              argumentName.slowToString()), node);
+          constantSystem.createString(new DartString.literal(argumentName),
+                                      node);
       argumentNames.add(graph.addConstant(argumentNameConstant, compiler));
     }
     var argumentNamesInstruction = buildLiteralList(argumentNames);
@@ -3544,7 +3540,7 @@
 
     List<HInstruction> inputs = <HInstruction>[];
 
-    String template = rti.getTypeRepresentation(argument, (variable) {
+    String template = rti.getTypeRepresentationWithHashes(argument, (variable) {
       inputs.add(addTypeVariableReference(variable));
     });
 
@@ -3657,7 +3653,7 @@
 
     ClassElement cls = constructor.getEnclosingClass();
     if (cls.isAbstract(compiler) && constructor.isGenerativeConstructor()) {
-      generateAbstractClassInstantiationError(send, cls.name.slowToString());
+      generateAbstractClassInstantiationError(send, cls.name);
       return;
     }
     if (backend.classNeedsRti(cls)) {
@@ -3866,10 +3862,10 @@
     List<String> existingArguments = <String>[];
     FunctionSignature signature = function.computeSignature(compiler);
     signature.forEachParameter((Element parameter) {
-      existingArguments.add(parameter.name.slowToString());
+      existingArguments.add(parameter.name);
     });
     generateThrowNoSuchMethod(diagnosticNode,
-                              function.name.slowToString(),
+                              function.name,
                               argumentNodes: argumentNodes,
                               existingArguments: existingArguments);
   }
@@ -3916,7 +3912,7 @@
     // optimizations.
     bool isOptimizableOperationOnIndexable(Selector selector, Element element) {
       bool isLength = selector.isGetter()
-          && selector.name == const SourceString("length");
+          && selector.name == "length";
       if (isLength || selector.isIndex()) {
         HType type = new HType.nonNullExact(
             element.getEnclosingClass(), compiler);
@@ -4056,7 +4052,7 @@
     Element element = elements[node];
     if (!Elements.isUnresolved(element) && element.impliesType()) {
       Identifier selector = node.selector;
-      generateThrowNoSuchMethod(node, selector.source.slowToString(),
+      generateThrowNoSuchMethod(node, selector.source,
                                 argumentNodes: node.arguments);
       return;
     }
@@ -4064,7 +4060,7 @@
     if (node.isSuperCall) {
       HInstruction result;
       List<HInstruction> setterInputs = <HInstruction>[];
-      if (identical(node.assignmentOperator.source.stringValue, '=')) {
+      if (identical(node.assignmentOperator.source, '=')) {
         addDynamicSendArgumentsToList(node, setterInputs);
         result = setterInputs.last;
       } else {
@@ -4116,7 +4112,7 @@
       }
       stack.add(result);
     } else if (node.isIndex) {
-      if (const SourceString("=") == op.source) {
+      if ("=" == op.source) {
         visitDynamicSend(node);
       } else {
         visit(node.receiver);
@@ -4148,7 +4144,7 @@
           stack.add(value);
         }
       }
-    } else if (const SourceString("=") == op.source) {
+    } else if ("=" == op.source) {
       Link<Node> link = node.arguments;
       assert(!link.isEmpty && link.tail.isEmpty);
       if (Elements.isInstanceSend(node, elements)) {
@@ -4159,12 +4155,11 @@
         visit(link.head);
         generateNonInstanceSetter(node, element, pop());
       }
-    } else if (identical(op.source.stringValue, "is")) {
+    } else if (identical(op.source, "is")) {
       compiler.internalError("is-operator as SendSet", node: op);
     } else {
-      assert(const SourceString("++") == op.source ||
-             const SourceString("--") == op.source ||
-             node.assignmentOperator.source.stringValue.endsWith("="));
+      assert("++" == op.source || "--" == op.source ||
+             node.assignmentOperator.source.endsWith("="));
 
       // [receiver] is only used if the node is an instance send.
       HInstruction receiver = null;
@@ -4956,8 +4951,8 @@
     jumpHandler.close();
   }
 
-  Element lookupOperator(ClassElement classElement, SourceString operatorName) {
-    SourceString dartMethodName =
+  Element lookupOperator(ClassElement classElement, String operatorName) {
+    String dartMethodName =
         Elements.constructOperatorName(operatorName, false);
     return classElement.lookupMember(dartMethodName);
   }
@@ -5009,7 +5004,7 @@
       open(startCatchBlock);
       // TODO(kasperl): Bad smell. We shouldn't be constructing elements here.
       // Note that the name of this element is irrelevant.
-      Element element = new ElementX(const SourceString('exception'),
+      Element element = new ElementX('exception',
                                      ElementKind.PARAMETER,
                                      currentElement);
       exception = new HLocalValue(element);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 0dff833..8c3fe05 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -31,10 +31,10 @@
     }
     // TODO(podivilov): find the right sourceFile here and remove offset checks
     // below.
-    if (beginToken.charOffset < sourceFile.text.length) {
+    if (beginToken.charOffset < sourceFile.length) {
       node.sourcePosition = new SourceFileLocation(sourceFile, beginToken);
     }
-    if (endToken.charOffset < sourceFile.text.length) {
+    if (endToken.charOffset < sourceFile.length) {
       node.endSourcePosition = new SourceFileLocation(sourceFile, endToken);
     }
     return node;
@@ -1503,7 +1503,7 @@
   visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
     use(node.receiver);
     js.Expression object = pop();
-    SourceString name = node.selector.name;
+    String name = node.selector.name;
     String methodName;
     List<js.Expression> arguments = visitArguments(node.inputs);
     Element target = node.element;
@@ -1714,7 +1714,7 @@
         // directly. Because `fetchLength` is a constant we use its
         // constant value instead.
         Element element = compiler.findRequiredElement(
-            compiler.typedDataLibrary, const SourceString('fetchLength'));
+            compiler.typedDataLibrary, 'fetchLength');
         Constant constant =
             compiler.constantHandler.getConstantForVariable(element);
         assert(invariant(element, constant != null,
@@ -1896,7 +1896,7 @@
         HRelational relational = input;
         BinaryOperation operation =
             relational.operation(backend.constantSystem);
-        String op = mapRelationalOperator(operation.name.stringValue, true);
+        String op = mapRelationalOperator(operation.name, true);
         visitRelational(input, op);
       } else {
         handledBySpecialCase = false;
@@ -2034,7 +2034,7 @@
   }
 
   void generateThrowWithHelper(String helperName, argument) {
-    Element helper = compiler.findHelper(new SourceString(helperName));
+    Element helper = compiler.findHelper(helperName);
     world.registerStaticUse(helper);
     js.VariableUse jsHelper =
         new js.VariableUse(backend.namer.isolateAccess(helper));
@@ -2063,7 +2063,7 @@
     HInstruction argument = node.inputs[0];
     use(argument);
 
-    Element helper = compiler.findHelper(new SourceString("throwExpression"));
+    Element helper = compiler.findHelper("throwExpression");
     world.registerStaticUse(helper);
 
     js.VariableUse jsHelper =
@@ -2600,7 +2600,7 @@
     FunctionElement helperElement;
     if (node.isBooleanConversionCheck) {
       helper =
-          const CheckedModeHelper(const SourceString('boolConversionCheck'));
+          const CheckedModeHelper('boolConversionCheck');
     } else {
       helper =
           backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck);
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 8526f63..a9da46b 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -44,45 +44,45 @@
 
   static InvokeDynamicSpecializer lookupSpecializer(Selector selector) {
     if (selector.kind == SelectorKind.INDEX) {
-      return selector.name == const SourceString('[]')
+      return selector.name == '[]'
           ? const IndexSpecializer()
           : const IndexAssignSpecializer();
     } else if (selector.kind == SelectorKind.OPERATOR) {
-      if (selector.name == const SourceString('unary-')) {
+      if (selector.name == 'unary-') {
         return const UnaryNegateSpecializer();
-      } else if (selector.name == const SourceString('~')) {
+      } else if (selector.name == '~') {
         return const BitNotSpecializer();
-      } else if (selector.name == const SourceString('+')) {
+      } else if (selector.name == '+') {
         return const AddSpecializer();
-      } else if (selector.name == const SourceString('-')) {
+      } else if (selector.name == '-') {
         return const SubtractSpecializer();
-      } else if (selector.name == const SourceString('*')) {
+      } else if (selector.name == '*') {
         return const MultiplySpecializer();
-      } else if (selector.name == const SourceString('/')) {
+      } else if (selector.name == '/') {
         return const DivideSpecializer();
-      } else if (selector.name == const SourceString('~/')) {
+      } else if (selector.name == '~/') {
         return const TruncatingDivideSpecializer();
-      } else if (selector.name == const SourceString('%')) {
+      } else if (selector.name == '%') {
         return const ModuloSpecializer();
-      } else if (selector.name == const SourceString('>>')) {
+      } else if (selector.name == '>>') {
         return const ShiftRightSpecializer();
-      } else if (selector.name == const SourceString('<<')) {
+      } else if (selector.name == '<<') {
         return const ShiftLeftSpecializer();
-      } else if (selector.name == const SourceString('&')) {
+      } else if (selector.name == '&') {
         return const BitAndSpecializer();
-      } else if (selector.name == const SourceString('|')) {
+      } else if (selector.name == '|') {
         return const BitOrSpecializer();
-      } else if (selector.name == const SourceString('^')) {
+      } else if (selector.name == '^') {
         return const BitXorSpecializer();
-      } else if (selector.name == const SourceString('==')) {
+      } else if (selector.name == '==') {
         return const EqualsSpecializer();
-      } else if (selector.name == const SourceString('<')) {
+      } else if (selector.name == '<') {
         return const LessSpecializer();
-      } else if (selector.name == const SourceString('<=')) {
+      } else if (selector.name == '<=') {
         return const LessEqualSpecializer();
-      } else if (selector.name == const SourceString('>')) {
+      } else if (selector.name == '>') {
         return const GreaterSpecializer();
-      } else if (selector.name == const SourceString('>=')) {
+      } else if (selector.name == '>=') {
         return const GreaterEqualSpecializer();
       }
     }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 12ab6f1..e05bc81 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -1017,10 +1017,10 @@
   // Compute the set of users of this instruction that is dominated by
   // [other]. If [other] is a user of [this], it is included in the
   // returned set.
-  Set<HInstruction> dominatedUsers(HInstruction other) {
+  Setlet<HInstruction> dominatedUsers(HInstruction other) {
     // Keep track of all instructions that we have to deal with later
     // and count the number of them that are in the current block.
-    Set<HInstruction> users = new Set<HInstruction>();
+    Setlet<HInstruction> users = new Setlet<HInstruction>();
     int usersInCurrentBlock = 0;
 
     // Run through all the users and see if they are dominated or
@@ -1063,7 +1063,7 @@
 
   void replaceAllUsersDominatedBy(HInstruction cursor,
                                   HInstruction newInstruction) {
-    Set<HInstruction> users = dominatedUsers(cursor);
+    Setlet<HInstruction> users = dominatedUsers(cursor);
     for (HInstruction user in users) {
       user.changeUse(this, newInstruction);
     }
@@ -1370,7 +1370,7 @@
   bool isIndexOperatorOnIndexablePrimitive(Compiler compiler) {
     return isInterceptedCall
         && selector.kind == SelectorKind.INDEX
-        && selector.name == const SourceString('[]')
+        && selector.name == '[]'
         && inputs[1].isIndexablePrimitive(compiler);
   }
 }
@@ -1955,7 +1955,7 @@
 class HParameterValue extends HLocalValue {
   HParameterValue(Element element) : super(element);
 
-  toString() => 'parameter ${sourceElement.name.slowToString()}';
+  toString() => 'parameter ${sourceElement.name}';
   accept(HVisitor visitor) => visitor.visitParameterValue(this);
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index eb206a2..ccbd6a52 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -1533,7 +1533,7 @@
   void changeUsesDominatedBy(HBasicBlock dominator,
                              HInstruction input,
                              HType convertedType) {
-    Set<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first);
+    Setlet<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first);
     if (dominatedUsers.isEmpty) return;
 
     HTypeKnown newInput = new HTypeKnown(convertedType, input);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index f59fc42..eab3ed8 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -273,24 +273,24 @@
   String visitExit(HExit node) => "exit";
 
   String visitFieldGet(HFieldGet node) {
-    String fieldName = node.element.name.slowToString();
+    String fieldName = node.element.name;
     return 'field get ${temporaryId(node.receiver)}.$fieldName';
   }
 
   String visitFieldSet(HFieldSet node) {
     String valueId = temporaryId(node.value);
-    String fieldName = node.element.name.slowToString();
+    String fieldName = node.element.name;
     return 'field set ${temporaryId(node.receiver)}.$fieldName to $valueId';
   }
 
   String visitLocalGet(HLocalGet node) {
-    String localName = node.element.name.slowToString();
+    String localName = node.element.name;
     return 'local get ${temporaryId(node.local)}.$localName';
   }
 
   String visitLocalSet(HLocalSet node) {
     String valueId = temporaryId(node.value);
-    String localName = node.element.name.slowToString();
+    String localName = node.element.name;
     return 'local set ${temporaryId(node.local)}.$localName to $valueId';
   }
 
@@ -345,7 +345,7 @@
 
   String visitInvokeDynamic(HInvokeDynamic invoke, String kind) {
     String receiver = temporaryId(invoke.receiver);
-    String name = invoke.selector.name.slowToString();
+    String name = invoke.selector.name;
     String target = "($kind) $receiver.$name";
     int offset = HInvoke.ARGUMENTS_OFFSET;
     List arguments = invoke.inputs.sublist(offset);
@@ -360,17 +360,17 @@
       => visitInvokeDynamic(node, "set");
 
   String visitInvokeStatic(HInvokeStatic invoke) {
-    String target = invoke.element.name.slowToString();
+    String target = invoke.element.name;
     return visitGenericInvoke("Invoke", target, invoke.inputs);
   }
 
   String visitInvokeSuper(HInvokeSuper invoke) {
-    String target = invoke.element.name.slowToString();
+    String target = invoke.element.name;
     return visitGenericInvoke("Invoke super", target, invoke.inputs);
   }
 
   String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
-    String target = invoke.element.name.slowToString();
+    String target = invoke.element.name;
     return visitGenericInvoke("Invoke constructor body", target, invoke.inputs);
   }
 
@@ -380,7 +380,7 @@
 
   String visitForeignNew(HForeignNew node) {
     return visitGenericInvoke("New",
-                              "${node.element.name.slowToString()}",
+                              "${node.element.name}",
                               node.inputs);
   }
 
@@ -413,11 +413,11 @@
   String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}";
 
   String visitParameterValue(HParameterValue node) {
-    return "p${node.sourceElement.name.slowToString()}";
+    return "p${node.sourceElement.name}";
   }
 
   String visitLocalValue(HLocalValue node) {
-    return "l${node.sourceElement.name.slowToString()}";
+    return "l${node.sourceElement.name}";
   }
 
   String visitPhi(HPhi phi) {
@@ -436,16 +436,16 @@
   String visitShiftLeft(HShiftLeft node) => handleInvokeBinary(node, '<<');
 
   String visitStatic(HStatic node)
-      => "Static ${node.element.name.slowToString()}";
+      => "Static ${node.element.name}";
 
   String visitLazyStatic(HLazyStatic node)
-      => "LazyStatic ${node.element.name.slowToString()}";
+      => "LazyStatic ${node.element.name}";
 
   String visitOneShotInterceptor(HOneShotInterceptor node)
       => visitInvokeDynamic(node, "one shot interceptor");
 
   String visitStaticStore(HStaticStore node) {
-    String lhs = node.element.name.slowToString();
+    String lhs = node.element.name;
     return "Static $lhs = ${temporaryId(node.inputs[0])}";
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 72351ba..d861e34 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -301,7 +301,7 @@
       pendingOptimizations.putIfAbsent(instruction, () => () {
         Selector selector = instruction.selector;
         if (selector.isOperator()
-            && selector.name != const SourceString('==')) {
+            && selector.name != '==') {
           if (checkReceiver(instruction)) {
             addAllUsersBut(instruction, instruction.inputs[1]);
           }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
index f8c46f1a..ec2cede 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
@@ -450,7 +450,9 @@
     return copyHandlers[block];
   }
 
-  void addNameUsed(String name) => allUsedNames.add(name);
+  void addNameUsed(String name) {
+    allUsedNames.add(name);
+  }
 
   bool hasName(HInstruction instruction) => ownName.containsKey(instruction);
 
@@ -547,14 +549,14 @@
     }
 
     if (instruction.sourceElement != null) {
-      name = allocateWithHint(instruction.sourceElement.name.slowToString());
+      name = allocateWithHint(instruction.sourceElement.name);
     } else {
       // We could not find an element for the instruction. If the
       // instruction is used by a phi, try to use the name of the phi.
       // Otherwise, just allocate a temporary name.
       HPhi phi = firstPhiUserWithElement(instruction);
       if (phi != null) {
-        name = allocateWithHint(phi.sourceElement.name.slowToString());
+        name = allocateWithHint(phi.sourceElement.name);
       } else {
         name = allocateTemporary();
       }
diff --git a/sdk/lib/_internal/compiler/implementation/string_validator.dart b/sdk/lib/_internal/compiler/implementation/string_validator.dart
index 77154b2..98ad8fa 100644
--- a/sdk/lib/_internal/compiler/implementation/string_validator.dart
+++ b/sdk/lib/_internal/compiler/implementation/string_validator.dart
@@ -19,11 +19,11 @@
   StringValidator(this.listener);
 
   DartString validateQuotedString(Token token) {
-    SourceString source = token.value;
+    String source = token.value;
     StringQuoting quoting = quotingFromString(source);
     int leftQuote = quoting.leftQuoteLength;
     int rightQuote = quoting.rightQuoteLength;
-    SourceString content = source.copyWithoutQuotes(leftQuote, rightQuote);
+    String content = copyWithoutQuotes(source, leftQuote, rightQuote);
     return validateString(token,
                           token.charOffset + leftQuote,
                           content,
@@ -33,20 +33,20 @@
   DartString validateInterpolationPart(Token token, StringQuoting quoting,
                                        {bool isFirst: false,
                                         bool isLast: false}) {
-    SourceString source = token.value;
+    String source = token.value;
     int leftQuote = 0;
     int rightQuote = 0;
     if (isFirst) leftQuote = quoting.leftQuoteLength;
     if (isLast) rightQuote = quoting.rightQuoteLength;
-    SourceString content = source.copyWithoutQuotes(leftQuote, rightQuote);
+    String content = copyWithoutQuotes(source, leftQuote, rightQuote);
     return validateString(token,
                           token.charOffset + leftQuote,
                           content,
                           quoting);
   }
 
-  static StringQuoting quotingFromString(SourceString sourceString) {
-    Iterator<int> source = sourceString.iterator;
+  static StringQuoting quotingFromString(String sourceString) {
+    Iterator<int> source = sourceString.codeUnits.iterator;
     bool raw = false;
     int quoteLength = 1;
     source.moveNext();
@@ -81,6 +81,18 @@
     return StringQuoting.getQuoting(quoteChar, raw, quoteLength);
   }
 
+  /**
+   * Return the string [string] witout its [initial] first and [terminal] last
+   * characters. This is intended to be used to remove quotes from string
+   * literals (including an initial 'r' for raw strings).
+   */
+  String copyWithoutQuotes(String string, int initial, int terminal) {
+    assert(0 <= initial);
+    assert(0 <= terminal);
+    assert(initial + terminal <= string.length);
+    return string.substring(initial, string.length - terminal);
+  }
+
   void stringParseError(String message, Token token, int offset) {
     listener.cancel("$message @ $offset", token : token);
   }
@@ -91,7 +103,7 @@
    */
   DartString validateString(Token token,
                             int startOffset,
-                            SourceString string,
+                            String string,
                             StringQuoting quoting) {
     // We need to check for invalid x and u escapes, for line
     // terminators in non-multiline strings, and for invalid Unicode
@@ -102,7 +114,8 @@
     bool containsEscape = false;
     bool previousWasLeadSurrogate = false;
     bool invalidUtf16 = false;
-    for(HasNextIterator<int> iter = new HasNextIterator(string.iterator);
+    var stringIter = string.codeUnits.iterator;
+    for(HasNextIterator<int> iter = new HasNextIterator(stringIter);
         iter.hasNext;
         length++) {
       index++;
diff --git a/sdk/lib/_internal/compiler/implementation/tools/find_file_to_parse.sh b/sdk/lib/_internal/compiler/implementation/tools/find_file_to_parse.sh
deleted file mode 100755
index f13d0a9..0000000
--- a/sdk/lib/_internal/compiler/implementation/tools/find_file_to_parse.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/bash
-
-find .. \( \
-    -name README.dart \
-    -o -name Examples_A03_t01.dart \
-    -o -name Examples_A03_t02.dart \
-    -o -name Examples_A07_t01.dart \
-    -o -name 13_3_1_Typedef_A01_t02.dart \
-    -o -name 13_3_1_Typedef_A01_t03.dart \
-    -o -name 13_3_1_Typedef_A01_t04.dart \
-    -o -name 13_3_1_Typedef_A01_t06.dart \
-    -o -name 13_3_1_Typedef_A05_t01.dart \
-    -o -name 13_3_1_Typedef_A05_t02.dart \
-    -o -name 13_3_1_Typedef_A05_t03.dart \
-    -o -name 13_3_1_Typedef_A06_t01.dart \
-    -o -name 13_3_1_Typedef_A06_t03.dart \
-    -o -name 13_3_1_Typedef_A06_t04.dart \
-    -o -name 13_7_Type_Void_A01_t06.dart \
-    -o -name 13_7_Type_Void_A01_t07.dart \
-    -o -name 02_1_Class_A02_t02.dart \
-    -o -name 'Map_operator\[\]_A01_t03.dart' \
-    -o -name 'Map_operator\[\]=_A01_t03.dart' \
-    -o -name int_operator_mul_A01_t01.dart \
-    -o -name Isolate_A01_t01.dart \
-    -o -name Isolate_A02_t01.dart \
-    -o -name IsNotClass4NegativeTest.dart \
-    -o -name NamedParameters9NegativeTest.dart \
-    -o -name ClassKeywordTest.dart \
-    -o -name Prefix19NegativeTest.dart \
-    -o -name Operator2NegativeTest.dart \
-    -o -name 02_1_Class_Construction_A16_t02.dart \
-    -o -name 02_1_Class_Construction_A19_t01.dart \
-    -o -name 02_2_Interface_A02_t02.dart \
-    -o -name 13_4_Interface_Types_A04_t01.dart \
-    -o -name 13_4_Interface_Types_A04_t02.dart \
-    -o -name MapLiteral2Test.dart \
-    -o -name Switch1NegativeTest.dart \
-    -o \( -type d -name xcodebuild \) \
-    -o \( -type d -name out \) \
-    -o \( -type d -name await \) \
-    \) -prune -o \
-    -name \*.dart -type f -print \
-    | grep -v /editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/internal/model/testsource/ClassTest.dart \
-    | grep -v /editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/internal/model/testsource/FunctionTest.dart \
-    | grep -v /compiler/javatests/com/google/dart/compiler/parser/StringsErrorsNegativeTest.dart \
-    | grep -v /compiler/javatests/com/google/dart/compiler/resolver/ClassImplementsUnknownInterfaceNegativeTest.dart \
-    | grep -v /tests/language/src/InterfaceFunctionTypeAlias1NegativeTest.dart \
-    | grep -v /tests/language/src/InterfaceFunctionTypeAlias2NegativeTest.dart \
-    | grep -v /tests/language/src/InterfaceInjection1NegativeTest.dart \
-    | grep -v /tests/language/src/InterfaceFunctionTypeAlias3NegativeTest.dart \
-    | grep -v /tests/language/src/InterfaceInjection2NegativeTest.dart \
-    | grep -v /tests/language/src/NewExpression2NegativeTest.dart \
-    | grep -v /tests/language/src/NewExpression3NegativeTest.dart \
-    | grep -v /tests/language/src/TestNegativeTest.dart \
-    | grep -v /editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/internal/model/testsource/BadErrorMessages.dart \
-    | grep -v /editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/internal/model/testsource/CoreRuntimeTypesTest.dart \
-    | grep -v /editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/internal/model/testsource/NamingTest.dart \
-    | grep -v /editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/internal/model/testsource/SpreadArgumentTest.dart \
-    | grep -v /tests/language/src/IsNotClass1NegativeTest.dart \
-    | grep -v /tests/language/src/Label8NegativeTest.dart \
-    | grep -v /tests/language/src/ListLiteralNegativeTest.dart \
-    | grep -v /tests/language/src/MapLiteralNegativeTest.dart \
-    | grep -v /tests/language/src/TryCatch2NegativeTest.dart \
-    | grep -v /tests/language/src/NewExpression1NegativeTest.dart \
-    | grep -v /tests/language/src/TryCatch4NegativeTest.dart \
-    | grep -v /tests/language/src/ParameterInitializer3NegativeTest.dart \
-    | grep -v /compiler/javatests/com/google/dart/compiler/parser/FactoryInitializersNegativeTest.dart \
-    | grep -v '/editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/formatter/testsource/test006$A_in.dart' \
-    | grep -v '/editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/formatter/testsource/test006$A_out.dart' \
-    | grep -v '/utils/dartdoc/dartdoc.dart' \
-    | xargs grep -L -E 'native|@compile-error|@needsreview'
diff --git a/sdk/lib/_internal/compiler/implementation/tools/mini_parser.dart b/sdk/lib/_internal/compiler/implementation/tools/mini_parser.dart
deleted file mode 100644
index 3e8db07..0000000
--- a/sdk/lib/_internal/compiler/implementation/tools/mini_parser.dart
+++ /dev/null
@@ -1,314 +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.
-
-library parser;
-
-import 'dart:io';
-import 'dart:typed_data';
-import 'dart:collection';
-import 'dart:utf';
-
-import '../elements/elements.dart';
-import '../scanner/scanner_implementation.dart';
-import '../scanner/scannerlib.dart';
-import '../tree/tree.dart';
-import '../util/characters.dart';
-import '../source_file.dart';
-import '../ssa/ssa.dart';
-
-import '../../compiler.dart' as api;
-
-part '../diagnostic_listener.dart';
-part '../scanner/byte_array_scanner.dart';
-part '../scanner/byte_strings.dart';
-
-int charCount = 0;
-Stopwatch stopwatch;
-
-void main() {
-  toolMain(new Options().arguments);
-}
-
-void toolMain(List<String> arguments) {
-  filesWithCrashes = [];
-  stopwatch = new Stopwatch();
-  MyOptions options = new MyOptions();
-
-  void printStats() {
-    int kb = (charCount / 1024).round();
-    String stats =
-        '$classCount classes (${kb}Kb) in ${stopwatch.elapsedMilliseconds}ms';
-    if (errorCount != 0) {
-      stats = '$stats with $errorCount errors';
-    }
-    if (options.diet) {
-      print('Diet parsed $stats.');
-    } else {
-      print('Parsed $stats.');
-    }
-    if (filesWithCrashes.length != 0) {
-      print('The following ${filesWithCrashes.length} files caused a crash:');
-      for (String file in filesWithCrashes) {
-        print(file);
-      }
-    }
-  }
-
-  for (String argument in arguments) {
-    if (argument == "--diet") {
-      options.diet = true;
-      continue;
-    }
-    if (argument == "--throw") {
-      options.throwOnError = true;
-      continue;
-    }
-    if (argument == "--scan-only") {
-      options.scanOnly = true;
-      continue;
-    }
-    if (argument == "--read-only") {
-      options.readOnly = true;
-      continue;
-    }
-    if (argument == "--ast") {
-      options.buildAst = true;
-      continue;
-    }
-    if (argument == "-") {
-      parseFilesFrom(stdin, options, printStats);
-      return;
-    }
-    stopwatch.start();
-    parseFile(argument, options);
-    stopwatch.stop();
-  }
-
-  printStats();
-}
-
-void parseFile(String filename, MyOptions options) {
-  List<int> bytes = read(filename);
-  charCount += bytes.length;
-  if (options.readOnly) return;
-  MySourceFile file = new MySourceFile(filename, bytes);
-  final Listener listener = options.buildAst
-      ? new MyNodeListener(file, options)
-      : new MyListener(file);
-  final Parser parser = options.diet
-      ? new PartialParser(listener)
-      : new Parser(listener);
-  try {
-    Token token = scan(file);
-    if (!options.scanOnly) parser.parseUnit(token);
-  } on ParserError catch (ex) {
-    if (options.throwOnError) {
-      rethrow;
-    } else {
-      print(ex);
-    }
-  } catch (ex) {
-    print('Error in file: $filename');
-    rethrow;
-  }
-  if (options.buildAst) {
-    MyNodeListener l = listener;
-    if (!l.nodes.isEmpty) {
-      String message = 'Stack not empty after parsing';
-      print(formatError(message, l.nodes.head.getBeginToken(),
-                        l.nodes.head.getEndToken(), file));
-      throw message;
-    }
-  }
-}
-
-Token scan(MySourceFile source) {
-  Scanner scanner = new ByteArrayScanner(source.rawText);
-  return scanner.tokenize();
-}
-
-var filesWithCrashes;
-
-void parseFilesFrom(InputStream input, MyOptions options, Function whenDone) {
-  void readLine(String line) {
-    stopwatch.start();
-    try {
-      parseFile(line, options);
-    } catch (ex, trace) {
-      filesWithCrashes.add(line);
-      print(ex);
-      print(trace);
-    }
-    stopwatch.stop();
-  }
-  forEachLine(input, readLine, whenDone);
-}
-
-void forEachLine(InputStream input,
-                 void lineHandler(String line),
-                 void closeHandler()) {
-  StringInputStream stringStream = new StringInputStream(input);
-  stringStream.onLine = () {
-    String line;
-    while ((line = stringStream.readLine()) != null) {
-      lineHandler(line);
-    }
-  };
-  stringStream.onClosed = closeHandler;
-}
-
-List<int> read(String filename) {
-  RandomAccessFile file = new File(filename).openSync();
-  bool threw = true;
-  try {
-    int size = file.lengthSync();
-    List<int> bytes = new Uint8List(size + 1);
-    file.readIntoSync(bytes, 0, size);
-    bytes[size] = $EOF;
-    threw = false;
-    return bytes;
-  } finally {
-    try {
-      file.closeSync();
-    } catch (ex) {
-      if (!threw) rethrow;
-    }
-  }
-}
-
-int classCount = 0;
-int errorCount = 0;
-
-class MyListener extends Listener {
-  final SourceFile file;
-
-  MyListener(this.file);
-
-  void beginClassDeclaration(Token token) {
-    classCount++;
-  }
-
-  void beginInterface(Token token) {
-    classCount++;
-  }
-
-  void error(String message, Token token) {
-    throw new ParserError(formatError(message, token, token, file));
-  }
-}
-
-String formatError(String message, Token beginToken, Token endToken,
-                   SourceFile file) {
-  ++errorCount;
-  if (beginToken == null) return '${file.filename}: $message';
-  String tokenString = endToken.toString();
-  int begin = beginToken.charOffset;
-  int end = endToken.charOffset + tokenString.length;
-  return file.getLocationMessage(message, begin, end, true, (x) => x);
-}
-
-class MyNodeListener extends NodeListener {
-  MyNodeListener(SourceFile file, MyOptions options)
-    : super(new MyCanceller(file, options), null);
-
-  void beginClassDeclaration(Token token) {
-    classCount++;
-  }
-
-  void beginInterface(Token token) {
-    classCount++;
-  }
-
-  void endClassDeclaration(int interfacesCount, Token beginToken,
-                           Token extendsKeyword, Token implementsKeyword,
-                           Token endToken) {
-    super.endClassDeclaration(interfacesCount, beginToken,
-                              extendsKeyword, implementsKeyword,
-                              endToken);
-    ClassNode node = popNode(); // Discard ClassNode and assert the type.
-  }
-
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
-    super.endTopLevelFields(count, beginToken, endToken);
-    VariableDefinitions node = popNode(); // Discard node and assert the type.
-  }
-
-  void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
-    super.endFunctionTypeAlias(typedefKeyword, endToken);
-    Typedef node = popNode(); // Discard Typedef and assert type type.
-  }
-
-  void endLibraryTag(bool hasPrefix, Token beginToken, Token endToken) {
-    super.endLibraryTag(hasPrefix, beginToken, endToken);
-    ScriptTag node = popNode(); // Discard ScriptTag and assert type type.
-  }
-
-  void log(message) {
-    print(message);
-  }
-}
-
-class MyCanceller implements DiagnosticListener {
-  final SourceFile file;
-  final MyOptions options;
-
-  MyCanceller(this.file, this.options);
-
-  void log(String message) {}
-
-  void cancel(String reason, {node, token, instruction, element}) {
-    Token beginToken;
-    Token endToken;
-    if (token != null) {
-      beginToken = token;
-      endToken = token;
-    } else if (node != null) {
-      beginToken = node.getBeginToken();
-      endToken = node.getEndToken();
-    }
-    String message = formatError(reason, beginToken, endToken, file);
-    if (options.throwOnError) throw new ParserError(message);
-    print(message);
-  }
-}
-
-class MyOptions {
-  bool diet = false;
-  bool throwOnError = false;
-  bool scanOnly = false;
-  bool readOnly = false;
-  bool buildAst = false;
-}
-
-class MySourceFile extends SourceFile {
-  final rawText;
-  var stringText;
-
-  MySourceFile(filename, this.rawText) : super(filename, null);
-
-  String get text {
-    if (rawText is String) {
-      return rawText;
-    } else {
-      if (stringText == null) {
-        stringText = new String.fromCharCodes(rawText);
-        if (stringText.endsWith('\u0000')) {
-          // Strip trailing NUL used by ByteArrayScanner to signal EOF.
-          stringText = stringText.substring(0, stringText.length - 1);
-        }
-      }
-      return stringText;
-    }
-  }
-
-  set text(String newText) {
-    throw "not supported";
-  }
-}
-
-class Mock {
-  const Mock();
-  bool get useColors => true;
-  internalError(message) { throw message.toString(); }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/tree/dartstring.dart b/sdk/lib/_internal/compiler/implementation/tree/dartstring.dart
index 80f2091..72d0b0c 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/dartstring.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/dartstring.dart
@@ -16,9 +16,9 @@
   // This is a convenience constructor. If you need a const literal DartString,
   // use [const LiteralDartString(string)] directly.
   factory DartString.literal(String string) => new LiteralDartString(string);
-  factory DartString.rawString(SourceString source, int length) =>
+  factory DartString.rawString(String source, int length) =>
       new RawSourceDartString(source, length);
-  factory DartString.escapedString(SourceString source, int length) =>
+  factory DartString.escapedString(String source, int length) =>
       new EscapedSourceDartString(source, length);
   factory DartString.concat(DartString first, DartString second) {
     if (first.isEmpty) return second;
@@ -26,9 +26,19 @@
     return new ConsDartString(first, second);
   }
   const DartString();
+
+  /**
+   * The length of this [DartString], which is the string length after
+   * escapes have been resolved.
+   */
   int get length;
   bool get isEmpty => length == 0;
+
   Iterator<int> get iterator;
+
+  /**
+   * The string represented by this [DartString].
+   */
   String slowToString();
 
   bool operator ==(var other) {
@@ -46,8 +56,11 @@
 
   int get hashCode => throw new UnsupportedError('DartString.hashCode');
 
+  /**
+   * A textual representation of this [DartString] with some debugging
+   * information.
+   */
   String toString() => "DartString#${length}:${slowToString()}";
-  SourceString get source;
 }
 
 
@@ -58,17 +71,20 @@
   final String string;
   const LiteralDartString(this.string);
   int get length => string.length;
-  Iterator<int> get iterator => new StringCodeIterator(string);
+  Iterator<int> get iterator => string.codeUnits.iterator;
   String slowToString() => string;
-  SourceString get source => new StringWrapper(string);
 }
 
 /**
- * A [DartString] where the content comes from a slice of the program source.
+ * A [DartString] whereSource the content comes from a slice of the program
+ * source.
  */
 abstract class SourceBasedDartString extends DartString {
-  String toStringCache = null;
-  final SourceString source;
+  /**
+   * The source string containing explicit escapes from which this [DartString]
+   * is built.
+   */
+  final String source;
   final int length;
   SourceBasedDartString(this.source, this.length);
   Iterator<int> get iterator;
@@ -80,12 +96,8 @@
  */
 class RawSourceDartString extends SourceBasedDartString {
   RawSourceDartString(source, length) : super(source, length);
-  Iterator<int> get iterator => source.iterator;
-  String slowToString() {
-    if (toStringCache != null) return toStringCache;
-    toStringCache  = source.slowToString();
-    return toStringCache;
-  }
+  Iterator<int> get iterator => source.codeUnits.iterator;
+  String slowToString() => source;
 }
 
 /**
@@ -93,9 +105,10 @@
  * escapes.
  */
 class EscapedSourceDartString extends SourceBasedDartString {
+  String toStringCache;
   EscapedSourceDartString(source, length) : super(source, length);
   Iterator<int> get iterator {
-    if (toStringCache != null) return new StringCodeIterator(toStringCache);
+    if (toStringCache != null) return toStringCache.codeUnits.iterator;
     return new StringEscapeIterator(source);
   }
   String slowToString() {
@@ -130,7 +143,7 @@
     toStringCache = left.slowToString() + right.slowToString();
     return toStringCache;
   }
-  SourceString get source => new StringWrapper(slowToString());
+  String get source => slowToString();
 }
 
 class ConsDartStringIterator implements Iterator<int> {
@@ -178,7 +191,7 @@
   final Iterator<int> source;
   int _current = null;
 
-  StringEscapeIterator(SourceString source) : this.source = source.iterator;
+  StringEscapeIterator(String source) : this.source = source.codeUnits.iterator;
 
   int get current => _current;
 
diff --git a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
index 9b9a6ad..42d97c6 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
@@ -361,20 +361,20 @@
   bool get isPostfix => argumentsNode is Postfix;
   bool get isCall => !isOperator && !isPropertyAccess;
   bool get isIndex =>
-      isOperator && identical(selector.asOperator().source.stringValue, '[]');
+      isOperator && identical(selector.asOperator().source, '[]');
   bool get isLogicalAnd =>
-      isOperator && identical(selector.asOperator().source.stringValue, '&&');
+      isOperator && identical(selector.asOperator().source, '&&');
   bool get isLogicalOr =>
-      isOperator && identical(selector.asOperator().source.stringValue, '||');
+      isOperator && identical(selector.asOperator().source, '||');
 
   bool get isTypeCast {
     return isOperator
-        && identical(selector.asOperator().source.stringValue, 'as');
+        && identical(selector.asOperator().source, 'as');
   }
 
   bool get isTypeTest {
     return isOperator
-        && identical(selector.asOperator().source.stringValue, 'is');
+        && identical(selector.asOperator().source, 'is');
   }
 
   bool get isIsNotCheck {
@@ -383,8 +383,8 @@
 
   TypeAnnotation get typeAnnotationFromIsCheckOrCast {
     assert(isOperator);
-    assert(identical(selector.asOperator().source.stringValue, 'is') ||
-        identical(selector.asOperator().source.stringValue, 'as'));
+    assert(identical(selector.asOperator().source, 'is') ||
+        identical(selector.asOperator().source, 'as'));
     return isIsNotCheck
         ? arguments.head.asSend().receiver
         : arguments.head;
@@ -496,7 +496,7 @@
   final Link<Node> nodes;
   final Token beginToken;
   final Token endToken;
-  final SourceString delimiter;
+  final String delimiter;
   bool get isEmpty => nodes.isEmpty;
 
   NodeList([this.beginToken, this.nodes, this.endToken, this.delimiter]);
@@ -773,7 +773,7 @@
     try {
       Token valueToken = token;
       if (identical(valueToken.kind, PLUS_TOKEN)) valueToken = valueToken.next;
-      return int.parse(valueToken.value.slowToString());
+      return int.parse(valueToken.value);
     } on FormatException catch (ex) {
       (this.handler)(token, ex);
     }
@@ -792,7 +792,7 @@
     try {
       Token valueToken = token;
       if (identical(valueToken.kind, PLUS_TOKEN)) valueToken = valueToken.next;
-      return double.parse(valueToken.value.slowToString());
+      return double.parse(valueToken.value);
     } on FormatException catch (ex) {
       (this.handler)(token, ex);
     }
@@ -915,12 +915,12 @@
   accept(Visitor visitor) => visitor.visitLiteralString(this);
 }
 
-class LiteralNull extends Literal<SourceString> {
+class LiteralNull extends Literal<String> {
   LiteralNull(Token token) : super(token, null);
 
   LiteralNull asLiteralNull() => this;
 
-  SourceString get value => null;
+  String get value => null;
 
   accept(Visitor visitor) => visitor.visitLiteralNull(this);
 }
@@ -975,13 +975,13 @@
 class Identifier extends Expression {
   final Token token;
 
-  SourceString get source => token.value;
+  String get source => token.value;
 
   Identifier(Token this.token);
 
-  bool isThis() => identical(source.stringValue, 'this');
+  bool isThis() => identical(source, 'this');
 
-  bool isSuper() => identical(source.stringValue, 'super');
+  bool isSuper() => identical(source, 'super');
 
   Identifier asIdentifier() => this;
 
@@ -1263,7 +1263,7 @@
   static int computeFlags(Link<Node> nodes) {
     int flags = 0;
     for (; !nodes.isEmpty; nodes = nodes.tail) {
-      String value = nodes.head.asIdentifier().source.stringValue;
+      String value = nodes.head.asIdentifier().source;
       if (identical(value, 'static')) flags |= FLAG_STATIC;
       else if (identical(value, 'abstract')) flags |= FLAG_ABSTRACT;
       else if (identical(value, 'final')) flags |= FLAG_FINAL;
@@ -1279,7 +1279,7 @@
   Node findModifier(String modifier) {
     Link<Node> nodeList = nodes.nodes;
     for (; !nodeList.isEmpty; nodeList = nodeList.tail) {
-      String value = nodeList.head.asIdentifier().source.stringValue;
+      String value = nodeList.head.asIdentifier().source;
       if(identical(value, modifier)) {
         return nodeList.head;
       }
@@ -1680,7 +1680,7 @@
 
   Label(this.identifier, this.colonToken);
 
-  String slowToString() => identifier.source.slowToString();
+  String get labelName => identifier.source;
 
   Label asLabel() => this;
 
diff --git a/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart b/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart
index 86a7ee6..cc398a6 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart
@@ -36,8 +36,8 @@
   /**
    * Adds given string to result string.
    */
-  void add(SourceString string) {
-    string.printOn(sb);
+  void add(String string) {
+    sb.write(string);
   }
 
   void addBeginAndEndTokensToParams(Node node, Map params) {
@@ -90,7 +90,9 @@
     params.forEach((k, v) {
       String value;
       if (v != null) {
-        value = v
+        var str = v;
+        if (v is Token) str = v.value;
+        value = str
             .replaceAll("<", "&lt;")
             .replaceAll(">", "&gt;")
             .replaceAll('"', "'");
@@ -201,7 +203,7 @@
   }
 
   visitIdentifier(Identifier node) {
-    openAndCloseNode(node, "Identifier", {"token" : node.token.slowToString()});
+    openAndCloseNode(node, "Identifier", {"token" : node.token});
   }
 
   visitIf(If node) {
@@ -259,7 +261,7 @@
 
   visitLiteralString(LiteralString node) {
     openAndCloseNode(node, "LiteralString",
-        {"value" : node.token.slowToString()});
+        {"value" : node.token});
   }
 
   visitMixinApplication(MixinApplication node) {
@@ -283,10 +285,7 @@
   }
 
   visitNodeList(NodeList node) {
-    var params = {
-        "delimiter" :
-            node.delimiter != null ? node.delimiter.stringValue : null
-    };
+    var params = { "delimiter" : node.delimiter };
     if (node.nodes.toList().length == 0) {
       openAndCloseNode(node, "NodeList", params);
     } else {
@@ -297,7 +296,7 @@
   }
 
   visitOperator(Operator node) {
-    openAndCloseNode(node, "Operator", {"value" : node.token.slowToString()});
+    openAndCloseNode(node, "Operator", {"value" : node.token});
   }
 
   visitParenthesizedExpression(ParenthesizedExpression node) {
diff --git a/sdk/lib/_internal/compiler/implementation/tree/unparser.dart b/sdk/lib/_internal/compiler/implementation/tree/unparser.dart
index 0ca2f98..960c8b6 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/unparser.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/unparser.dart
@@ -17,8 +17,8 @@
 
   Unparser() : sb = new StringBuffer();
 
-  void add(SourceString string) {
-    string.printOn(sb);
+  void add(String string) {
+    sb.write(string);
   }
 
   void addToken(Token token) {
@@ -147,7 +147,7 @@
         Identifier identifier = send.selector.asIdentifier();
         if (identical(identifier.token.kind, KEYWORD_TOKEN)) {
           sb.write(' ');
-        } else if (identifier.source == const SourceString('negate')) {
+        } else if (identifier.source == 'negate') {
           // TODO(ahe): Remove special case for negate.
           sb.write(' ');
         }
@@ -298,7 +298,7 @@
 
   visitSend(Send node) {
     Operator op = node.selector.asOperator();
-    String opString = op != null ? op.source.stringValue : null;
+    String opString = op != null ? op.source : null;
     bool spacesNeeded = identical(opString, 'is') || identical(opString, 'as');
 
     if (node.isPrefix) visit(node.selector);
@@ -333,7 +333,7 @@
       visit(node.selector);
       if (!node.isPrefix) {
         visit(node.assignmentOperator);
-        if (node.assignmentOperator.source.slowToString() != '=') sb.write(' ');
+        if (node.assignmentOperator.source != '=') sb.write(' ');
       }
       visit(node.argumentsNode);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/tree_validator.dart b/sdk/lib/_internal/compiler/implementation/tree_validator.dart
index ce3809e..5204ed6 100644
--- a/sdk/lib/_internal/compiler/implementation/tree_validator.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree_validator.dart
@@ -38,7 +38,7 @@
 
   visitSendSet(SendSet node) {
     final selector = node.selector;
-    final name = node.assignmentOperator.source.stringValue;
+    final name = node.assignmentOperator.source;
     final arguments = node.arguments;
 
     expect(node, arguments != null);
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 8545eaa..9aa6409 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -37,7 +37,6 @@
   String toString() => name;
 }
 
-
 /**
  * [ElementAccess] represents the access of [element], either as a property
  * access or invocation.
@@ -160,6 +159,47 @@
   String toString() => 'TypeLiteralAccess($element)';
 }
 
+/// An is-expression that potentially promotes a variable.
+class TypePromotion {
+  final Send node;
+  final VariableElement variable;
+  final DartType type;
+  final List<TypePromotionMessage> messages = <TypePromotionMessage>[];
+
+  TypePromotion(this.node, this.variable, this.type);
+
+  bool get isValid => messages.isEmpty;
+
+  TypePromotion copy() {
+    return new TypePromotion(node, variable, type)..messages.addAll(messages);
+  }
+
+  void addHint(Spannable spannable, MessageKind kind, [Map arguments]) {
+    messages.add(new TypePromotionMessage(api.Diagnostic.HINT,
+        spannable, kind, arguments));
+  }
+
+  void addInfo(Spannable spannable, MessageKind kind, [Map arguments]) {
+    messages.add(new TypePromotionMessage(api.Diagnostic.INFO,
+        spannable, kind, arguments));
+  }
+
+  String toString() {
+    return 'Promote ${variable} to ${type}';
+  }
+}
+
+/// A hint or info message attached to a type promotion.
+class TypePromotionMessage {
+  api.Diagnostic diagnostic;
+  Spannable spannable;
+  MessageKind messageKind;
+  Map messageArguments;
+
+  TypePromotionMessage(this.diagnostic, this.spannable, this.messageKind,
+                       [this.messageArguments]);
+}
+
 class TypeCheckerVisitor extends Visitor<DartType> {
   final Compiler compiler;
   final TreeElements elements;
@@ -182,43 +222,60 @@
   DartType objectType;
   DartType listType;
 
-  Map<Node, Map<VariableElement, DartType>> shownTypesMap =
-      new Map<Node, Map<VariableElement, DartType>>();
+  Map<Node, List<TypePromotion>> shownTypePromotionsMap =
+      new Map<Node, List<TypePromotion>>();
 
-  Map<VariableElement, Link<DartType>> knownTypesMap =
-      new Map<VariableElement, Link<DartType>>();
+  Map<VariableElement, Link<TypePromotion>> typePromotionsMap =
+      new Map<VariableElement, Link<TypePromotion>>();
 
-  void showType(Node node, VariableElement element, DartType type) {
-    Map<VariableElement, DartType> shownTypes = shownTypesMap.putIfAbsent(node,
-        () => new Map<VariableElement, DartType>());
-    shownTypes[element] = type;
+  Set<TypePromotion> reportedTypePromotions = new Set<TypePromotion>();
+
+  void showTypePromotion(Node node, TypePromotion typePromotion) {
+    List<TypePromotion> shownTypePromotions =
+        shownTypePromotionsMap.putIfAbsent(node, () => <TypePromotion>[]);
+    shownTypePromotions.add(typePromotion);
   }
 
-  void registerKnownType(VariableElement element, DartType type) {
-    Link<DartType> knownTypes =
-        knownTypesMap.putIfAbsent(element, () => const Link<DartType>());
-    knownTypesMap[element] = knownTypes.prepend(type);
+  void registerKnownTypePromotion(TypePromotion typePromotion) {
+    VariableElement variable = typePromotion.variable;
+    Link<TypePromotion> knownTypes =
+        typePromotionsMap.putIfAbsent(variable,
+                                      () => const Link<TypePromotion>());
+    typePromotionsMap[variable] = knownTypes.prepend(typePromotion);
   }
 
-  void unregisterKnownType(VariableElement element) {
-    Link<DartType> knownTypes = knownTypesMap[element].tail;
+  void unregisterKnownTypePromotion(TypePromotion typePromotion) {
+    VariableElement variable = typePromotion.variable;
+    Link<TypePromotion> knownTypes = typePromotionsMap[variable].tail;
     if (knownTypes.isEmpty) {
-      knownTypesMap.remove(element);
+      typePromotionsMap.remove(variable);
     } else {
-      knownTypesMap[element] = knownTypes;
+      typePromotionsMap[variable] = knownTypes;
     }
   }
 
-  Map<VariableElement, DartType> getShownTypesFor(Node node) {
-    Map<VariableElement, DartType> shownTypes = shownTypesMap[node];
-    return shownTypes != null ? shownTypes : const {};
+  List<TypePromotion> getShownTypePromotionsFor(Node node) {
+    List<TypePromotion> shownTypePromotions = shownTypePromotionsMap[node];
+    return shownTypePromotions != null ? shownTypePromotions : const [];
+  }
+
+  TypePromotion getKnownTypePromotion(VariableElement element) {
+    Link<TypePromotion> promotions = typePromotionsMap[element];
+    if (promotions != null) {
+      while (!promotions.isEmpty) {
+        TypePromotion typePromotion = promotions.head;
+        if (typePromotion.isValid) {
+          return typePromotion;
+        }
+        promotions = promotions.tail;
+      }
+    }
+    return null;
   }
 
   DartType getKnownType(VariableElement element) {
-    Link<DartType> promotions = knownTypesMap[element];
-    if (promotions != null) {
-      return promotions.head;
-    }
+    TypePromotion typePromotion = getKnownTypePromotion(element);
+    if (typePromotion != null) return typePromotion.type;
     return element.computeType(compiler);
   }
 
@@ -247,8 +304,27 @@
   }
 
   reportTypeInfo(Spannable node, MessageKind kind, [Map arguments = const {}]) {
-    compiler.reportDiagnostic(compiler.spanFromSpannable(node),
-        '${kind.message(arguments)}', api.Diagnostic.INFO);
+    compiler.reportInfo(node, kind, arguments);
+  }
+
+  reportTypePromotionHint(TypePromotion typePromotion) {
+    if (!reportedTypePromotions.contains(typePromotion)) {
+      reportedTypePromotions.add(typePromotion);
+      for (TypePromotionMessage message in typePromotion.messages) {
+        switch (message.diagnostic) {
+          case api.Diagnostic.HINT:
+            compiler.reportHint(message.spannable,
+                                message.messageKind,
+                                message.messageArguments);
+            break;
+          case api.Diagnostic.INFO:
+            compiler.reportInfo(message.spannable,
+                                message.messageKind,
+                                message.messageArguments);
+            break;
+        }
+      }
+    }
   }
 
   // TODO(karlklose): remove these functions.
@@ -285,27 +361,84 @@
     return result;
   }
 
+  void checkTypePromotion(Node node, TypePromotion typePromotion,
+                          {bool checkAccesses: false}) {
+    VariableElement variable = typePromotion.variable;
+    String variableName = variable.name;
+    List<Node> potentialMutationsIn =
+        elements.getPotentialMutationsIn(node, variable);
+    if (!potentialMutationsIn.isEmpty) {
+      typePromotion.addHint(typePromotion.node,
+          MessageKind.POTENTIAL_MUTATION,
+          {'variableName': variableName, 'shownType': typePromotion.type});
+      for (Node mutation in potentialMutationsIn) {
+        typePromotion.addInfo(mutation,
+            MessageKind.POTENTIAL_MUTATION_HERE,
+            {'variableName': variableName});
+      }
+    }
+    List<Node> potentialMutationsInClosures =
+        elements.getPotentialMutationsInClosure(variable);
+    if (!potentialMutationsInClosures.isEmpty) {
+      typePromotion.addHint(typePromotion.node,
+          MessageKind.POTENTIAL_MUTATION_IN_CLOSURE,
+          {'variableName': variableName, 'shownType': typePromotion.type});
+      for (Node mutation in potentialMutationsInClosures) {
+        typePromotion.addInfo(mutation,
+            MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE,
+            {'variableName': variableName});
+      }
+    }
+    if (checkAccesses) {
+      List<Node> accesses = elements.getAccessesByClosureIn(node, variable);
+      List<Node> mutations = elements.getPotentialMutations(variable);
+      if (!accesses.isEmpty && !mutations.isEmpty) {
+        typePromotion.addHint(typePromotion.node,
+            MessageKind.ACCESSED_IN_CLOSURE,
+            {'variableName': variableName, 'shownType': typePromotion.type});
+        for (Node access in accesses) {
+          typePromotion.addInfo(access,
+              MessageKind.ACCESSED_IN_CLOSURE_HERE,
+              {'variableName': variableName});
+        }
+        for (Node mutation in mutations) {
+          typePromotion.addInfo(mutation,
+              MessageKind.POTENTIAL_MUTATION_HERE,
+              {'variableName': variableName});
+        }
+      }
+    }
+  }
+
+  void reshowTypePromotions(Node node, Node receiver, Node argument) {
+    for (TypePromotion typePromotion in  getShownTypePromotionsFor(receiver)) {
+      typePromotion = typePromotion.copy();
+      checkTypePromotion(argument, typePromotion);
+      showTypePromotion(node, typePromotion);
+    }
+
+    for (TypePromotion typePromotion in getShownTypePromotionsFor(argument)) {
+      typePromotion = typePromotion.copy();
+      checkTypePromotion(argument, typePromotion);
+      showTypePromotion(node, typePromotion);
+    }
+  }
+
   /// Analyze [node] in the context of the known types shown in [context].
   DartType analyzeInPromotedContext(Node context, Node node) {
-    Link<VariableElement> knownForArgument = const Link<VariableElement>();
-    Map<VariableElement, DartType> shownForReceiver =
-        getShownTypesFor(context);
-    shownForReceiver.forEach((VariableElement variable, DartType type) {
-      if (elements.isPotentiallyMutatedIn(node, variable)) return;
-      if (elements.isPotentiallyMutatedInClosure(variable)) return;
-      if (elements.isAccessedByClosureIn(node, variable) &&
-          elements.isPotentiallyMutated(variable)) {
-        return;
-      }
-      knownForArgument = knownForArgument.prepend(variable);
-      registerKnownType(variable, type);
-    });
+    Link<TypePromotion> knownForNode = const Link<TypePromotion>();
+    for (TypePromotion typePromotion in  getShownTypePromotionsFor(context)) {
+      typePromotion = typePromotion.copy();
+      checkTypePromotion(node, typePromotion, checkAccesses: true);
+      knownForNode = knownForNode.prepend(typePromotion);
+      registerKnownTypePromotion(typePromotion);
+    }
 
     final DartType type = analyze(node);
 
-    while (!knownForArgument.isEmpty) {
-      unregisterKnownType(knownForArgument.head);
-      knownForArgument = knownForArgument.tail;
+    while (!knownForNode.isEmpty) {
+      unregisterKnownTypePromotion(knownForNode.head);
+      knownForNode = knownForNode.tail;
     }
 
     return type;
@@ -464,9 +597,9 @@
     return thenType.join(elseType);
   }
 
-  void checkPrivateAccess(Node node, Element element, SourceString name) {
+  void checkPrivateAccess(Node node, Element element, String name) {
     if (name != null &&
-        name.isPrivate() &&
+        isPrivateName(name) &&
         element.getLibrary() != currentLibrary) {
       reportTypeWarning(
           node,
@@ -477,57 +610,75 @@
 
   }
 
-  ElementAccess lookupMember(Node node, DartType type, SourceString name,
-                             MemberKind memberKind) {
-    if (type.treatAsDynamic) {
+  ElementAccess lookupMember(Node node, DartType receiverType, String name,
+                             MemberKind memberKind, Element receiverElement) {
+    if (receiverType.treatAsDynamic) {
       return const DynamicAccess();
     }
-    DartType originalType = type;
-    while (identical(type.kind, TypeKind.TYPE_VARIABLE)) {
-      TypeVariableType variable = type;
-      type = variable.element.bound;
-      if (type == originalType) {
-        type = compiler.objectClass.rawType;
+    Member getMember(DartType type) {
+      DartType originalType = type;
+      while (identical(type.kind, TypeKind.TYPE_VARIABLE)) {
+        TypeVariableType variable = type;
+        type = variable.element.bound;
+        if (type == originalType) {
+          type = compiler.objectClass.rawType;
+        }
       }
+      if (type.kind == TypeKind.FUNCTION || type.kind == TypeKind.TYPEDEF) {
+        // TODO(karlklose): handle calling `call` on the function type. Do we
+        // have to type-check the arguments against the function type?
+        type = compiler.functionClass.rawType;
+      }
+      assert(invariant(node, type.kind == TypeKind.INTERFACE,
+          message: "unexpected type kind ${type.kind}."));
+      InterfaceType interface = type;
+      return interface.lookupMember(name,
+          isSetter: identical(memberKind, MemberKind.SETTER));
     }
-    if (type.kind == TypeKind.FUNCTION || type.kind == TypeKind.TYPEDEF) {
-      // TODO(karlklose): handle calling `call` on the function type. Do we have
-      // to type-check the arguments against the function type.
-      type = compiler.functionClass.rawType;
-    }
-    assert(invariant(node, type.kind == TypeKind.INTERFACE,
-        message: "unexpected type kind ${type.kind}."));
-    InterfaceType interface = type;
-    Member member = interface.lookupMember(name,
-        isSetter: identical(memberKind, MemberKind.SETTER));
+    Member member = getMember(receiverType);
     if (member != null) {
       checkPrivateAccess(node, member.element, name);
       return new MemberAccess(member);
     }
+    if (receiverElement != null &&
+        (receiverElement.isVariable() || receiverElement.isParameter())) {
+      Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement];
+      if (typePromotions != null) {
+        while (!typePromotions.isEmpty) {
+          TypePromotion typePromotion = typePromotions.head;
+          if (!typePromotion.isValid) {
+            if (getMember(typePromotion.type) != null) {
+              reportTypePromotionHint(typePromotion);
+            }
+          }
+          typePromotions = typePromotions.tail;
+        }
+      }
+    }
     switch (memberKind) {
       case MemberKind.METHOD:
         reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND,
-            {'className': type.name, 'memberName': name});
+            {'className': receiverType.name, 'memberName': name});
         break;
       case MemberKind.OPERATOR:
         reportTypeWarning(node, MessageKind.OPERATOR_NOT_FOUND,
-            {'className': type.name, 'memberName': name});
+            {'className': receiverType.name, 'memberName': name});
         break;
       case MemberKind.GETTER:
         reportTypeWarning(node, MessageKind.MEMBER_NOT_FOUND.warning,
-            {'className': type.name, 'memberName': name});
+            {'className': receiverType.name, 'memberName': name});
         break;
       case MemberKind.SETTER:
         reportTypeWarning(node, MessageKind.PROPERTY_NOT_FOUND,
-            {'className': type.name, 'memberName': name});
+            {'className': receiverType.name, 'memberName': name});
         break;
     }
     return const DynamicAccess();
   }
 
-  DartType lookupMemberType(Node node, DartType type, SourceString name,
+  DartType lookupMemberType(Node node, DartType type, String name,
                             MemberKind memberKind) {
-    return lookupMember(node, type, name, memberKind).computeType(compiler);
+    return lookupMember(node, type, name, memberKind, null).computeType(compiler);
   }
 
   void analyzeArguments(Send send, Element element, DartType type,
@@ -545,7 +696,7 @@
         NamedArgument namedArgument = argument.asNamedArgument();
         if (namedArgument != null) {
           argument = namedArgument.expression;
-          SourceString argumentName = namedArgument.name.source;
+          String argumentName = namedArgument.name.source;
           DartType namedParameterType =
               funType.getNamedParameterType(argumentName);
           if (namedParameterType == null) {
@@ -637,7 +788,7 @@
    * Computes the [ElementAccess] for [name] on the [node] possibly using the
    * [element] provided for [node] by the resolver.
    */
-  ElementAccess computeAccess(Send node, SourceString name, Element element,
+  ElementAccess computeAccess(Send node, String name, Element element,
                               MemberKind memberKind) {
     if (element != null && element.isErroneous()) {
       // An error has already been reported for this node.
@@ -658,7 +809,8 @@
         return const DynamicAccess();
       }
       TypeKind receiverKind = receiverType.kind;
-      return lookupMember(node, receiverType, name, memberKind);
+      return lookupMember(node, receiverType, name, memberKind,
+          elements[node.receiver]);
     } else {
       return computeResolvedAccess(node, name, element, memberKind);
     }
@@ -668,11 +820,11 @@
    * Computes the [ElementAccess] for [name] on the [node] using the [element]
    * provided for [node] by the resolver.
    */
-  ElementAccess computeResolvedAccess(Send node, SourceString name,
+  ElementAccess computeResolvedAccess(Send node, String name,
                                       Element element, MemberKind memberKind) {
     if (element == null) {
       // foo() where foo is unresolved.
-      return lookupMember(node, thisType, name, memberKind);
+      return lookupMember(node, thisType, name, memberKind, null);
     } else if (element.isErroneous()) {
       // foo() where foo is erroneous.
       return const DynamicAccess();
@@ -688,7 +840,7 @@
       return createResolvedAccess(node, name, element);
     } else if (element.isMember()) {
       // foo() where foo is an instance member.
-      return lookupMember(node, thisType, name, memberKind);
+      return lookupMember(node, thisType, name, memberKind, null);
     } else if (element.isFunction()) {
       // foo() where foo is a method in the same class.
       return createResolvedAccess(node, name, element);
@@ -705,7 +857,7 @@
     }
   }
 
-  ElementAccess createResolvedAccess(Send node, SourceString name,
+  ElementAccess createResolvedAccess(Send node, String name,
                                      Element element) {
     checkPrivateAccess(node, element, name);
     return createPromotedAccess(element);
@@ -713,9 +865,9 @@
 
   ElementAccess createPromotedAccess(Element element) {
     if (element.isVariable() || element.isParameter()) {
-      Link<DartType> knownTypes = knownTypesMap[element];
-      if (knownTypes != null) {
-        return new PromotedAccess(element, knownTypes.head);
+      TypePromotion typePromotion = getKnownTypePromotion(element);
+      if (typePromotion != null) {
+        return new PromotedAccess(element, typePromotion.type);
       }
     }
     return new ResolvedAccess(element);
@@ -725,7 +877,7 @@
    * Computes the type of the access of [name] on the [node] possibly using the
    * [element] provided for [node] by the resolver.
    */
-  DartType computeAccessType(Send node, SourceString name, Element element,
+  DartType computeAccessType(Send node, String name, Element element,
                              MemberKind memberKind) {
     DartType type =
         computeAccess(node, name, element, memberKind).computeType(compiler);
@@ -766,7 +918,7 @@
     }
 
     Identifier selector = node.selector.asIdentifier();
-    String name = selector.source.stringValue;
+    String name = selector.source;
 
     if (node.isOperator && identical(name, 'is')) {
       analyze(node.receiver);
@@ -776,10 +928,28 @@
             (variable.isVariable() || variable.isParameter())) {
           DartType knownType = getKnownType(variable);
           if (!knownType.isDynamic) {
-            DartType isType = elements.getType(node.arguments.head);
-            if (types.isMoreSpecific(isType, knownType)) {
-              showType(node, variable, isType);
+            DartType shownType = elements.getType(node.arguments.head);
+            TypePromotion typePromotion =
+                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});
+              }
             }
+            showTypePromotion(node, typePromotion);
           }
         }
       }
@@ -809,14 +979,7 @@
         final DartType argumentType =
             analyzeInPromotedContext(receiver, argument);
 
-        void reshowTypes(VariableElement variable, DartType type) {
-          if (elements.isPotentiallyMutatedIn(argument, variable)) return;
-          if (elements.isPotentiallyMutatedInClosure(variable)) return;
-          showType(node, variable, type);
-        }
-
-        getShownTypesFor(receiver).forEach(reshowTypes);
-        getShownTypesFor(argument).forEach(reshowTypes);
+        reshowTypePromotions(node, receiver, argument);
 
         checkAssignable(argument, argumentType, boolType);
         return boolType;
@@ -826,9 +989,9 @@
       } else if (identical(name, '?')) {
         return boolType;
       }
-      SourceString operatorName = selector.source;
+      String operatorName = selector.source;
       if (identical(name, '-') && node.arguments.isEmpty) {
-        operatorName = const SourceString('unary-');
+        operatorName = 'unary-';
       }
       assert(invariant(node,
                        identical(name, '+') || identical(name, '=') ||
@@ -846,13 +1009,14 @@
       // TODO(karlklose): handle `void` in expression context by calling
       // [analyzeNonVoid] instead of [analyze].
       ElementAccess access = receiverType.isVoid ? const DynamicAccess()
-          : lookupMember(node, receiverType, operatorName, MemberKind.OPERATOR);
+          : lookupMember(node, receiverType, operatorName,
+                         MemberKind.OPERATOR, null);
       LinkBuilder<DartType> argumentTypesBuilder = new LinkBuilder<DartType>();
       DartType resultType =
           analyzeInvocation(node, access, argumentTypesBuilder);
       if (identical(receiverType.element, compiler.intClass)) {
         if (identical(name, '+') ||
-            identical(operatorName, const SourceString('-')) ||
+            identical(operatorName, '-') ||
             identical(name, '*') ||
             identical(name, '%')) {
           DartType argumentType = argumentTypesBuilder.toLink().head;
@@ -897,7 +1061,7 @@
    * like [: target++ :].
    */
   DartType checkAssignmentOperator(SendSet node,
-                                   SourceString operatorName,
+                                   String operatorName,
                                    Node valueNode,
                                    DartType value) {
     assert(invariant(node, !node.isIndex));
@@ -933,7 +1097,7 @@
    * like [: base[key]++ :].
    */
   DartType checkIndexAssignmentOperator(SendSet node,
-                                        SourceString operatorName,
+                                        String operatorName,
                                         Node valueNode,
                                         DartType value) {
     assert(invariant(node, node.isIndex));
@@ -943,7 +1107,7 @@
 
     // [indexGet] is the type of operator[] on [base].
     DartType indexGet = lookupMemberType(
-        node, base, const SourceString('[]'), MemberKind.OPERATOR);
+        node, base, '[]', MemberKind.OPERATOR);
     if (indexGet is FunctionType) {
       FunctionType indexGetType = indexGet;
       DartType indexGetKey = firstType(indexGetType.parameterTypes);
@@ -967,7 +1131,7 @@
 
         // [indexSet] is the type of operator[]= on [base].
         DartType indexSet = lookupMemberType(
-            node, base, const SourceString('[]='), MemberKind.OPERATOR);
+            node, base, '[]=', MemberKind.OPERATOR);
         if (indexSet is FunctionType) {
           FunctionType indexSetType = indexSet;
           DartType indexSetKey = firstType(indexSetType.parameterTypes);
@@ -992,7 +1156,7 @@
   visitSendSet(SendSet node) {
     Element element = elements[node];
     Identifier selector = node.selector;
-    final name = node.assignmentOperator.source.stringValue;
+    final name = node.assignmentOperator.source;
     if (identical(name, '=')) {
       // e1 = value
       if (node.isIndex) {
@@ -1003,7 +1167,7 @@
         final Node valueNode = node.arguments.tail.head;
         final DartType value = analyze(valueNode);
         DartType indexSet = lookupMemberType(
-            node, base, const SourceString('[]='), MemberKind.OPERATOR);
+            node, base, '[]=', MemberKind.OPERATOR);
         if (indexSet is FunctionType) {
           FunctionType indexSetType = indexSet;
           DartType indexSetKey = firstType(indexSetType.parameterTypes);
@@ -1023,8 +1187,7 @@
       }
     } else if (identical(name, '++') || identical(name, '--')) {
       // e++ or e--
-      SourceString operatorName = identical(name, '++')
-          ? const SourceString('+') : const SourceString('-');
+      String operatorName = identical(name, '++') ? '+' : '-';
       if (node.isIndex) {
         // base[key]++, base[key]--, ++base[key], or --base[key]
         return checkIndexAssignmentOperator(
@@ -1036,19 +1199,19 @@
       }
     } else {
       // e1 o= e2 for some operator o.
-      SourceString operatorName;
+      String operatorName;
       switch (name) {
-        case '+=': operatorName = const SourceString('+'); break;
-        case '-=': operatorName = const SourceString('-'); break;
-        case '*=': operatorName = const SourceString('*'); break;
-        case '/=': operatorName = const SourceString('/'); break;
-        case '%=': operatorName = const SourceString('%'); break;
-        case '~/=': operatorName = const SourceString('~/'); break;
-        case '&=': operatorName = const SourceString('&'); break;
-        case '|=': operatorName = const SourceString('|'); break;
-        case '^=': operatorName = const SourceString('^'); break;
-        case '<<=': operatorName = const SourceString('<<'); break;
-        case '>>=': operatorName = const SourceString('>>'); break;
+        case '+=': operatorName = '+'; break;
+        case '-=': operatorName = '-'; break;
+        case '*=': operatorName = '*'; break;
+        case '/=': operatorName = '/'; break;
+        case '%=': operatorName = '%'; break;
+        case '~/=': operatorName = '~/'; break;
+        case '&=': operatorName = '&'; break;
+        case '|=': operatorName = '|'; break;
+        case '^=': operatorName = '^'; break;
+        case '<<=': operatorName = '<<'; break;
+        case '>>=': operatorName = '>>'; break;
         default:
           compiler.internalError(
               'Unexpected assignment operator $name', node: node);
@@ -1332,7 +1495,7 @@
     ClassElement cls = type.element;
     if (cls == compiler.doubleClass) return true;
     if (cls == compiler.intClass || cls == compiler.stringClass) return false;
-    Element equals = cls.lookupMember(const SourceString('=='));
+    Element equals = cls.lookupMember('==');
     return equals.getEnclosingClass() != compiler.objectClass;
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index fb77255..ac39ab2 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -51,7 +51,7 @@
   }
   int get hashCode => element.hashCode;
   String toString() {
-    return element == null ? 'toplevel' : element.name.slowToString();
+    return element == null ? 'toplevel' : element.name;
   }
   bool isClass() => true;
   bool isUnknown() => false;
@@ -450,7 +450,7 @@
 
   toString() {
     final elementType = methodOrField.isField() ? "field" : "method";
-    final elementRepresentation = methodOrField.name.slowToString();
+    final elementRepresentation = methodOrField.name;
     return "{ $elementType = $elementRepresentation"
            ", environment = $environment }";
   }
@@ -695,7 +695,7 @@
    * A map from method names to callers of methods with this name on objects
    * of unknown inferred type.
    */
-  final Map<SourceString, Set<FunctionElement>> dynamicCallers;
+  final Map<String, Set<FunctionElement>> dynamicCallers;
 
   /** The inferred type of elements stored in Lists. */
   ConcreteType listElementType;
@@ -723,7 +723,7 @@
         callers = new Map<FunctionElement, Set<Element>>(),
         readers = new Map<Element, Set<Element>>(),
         seenClasses = new Set<ClassElement>(),
-        dynamicCallers = new Map<SourceString, Set<FunctionElement>>(),
+        dynamicCallers = new Map<String, Set<FunctionElement>>(),
         inferredSelectorTypes = new Map<Selector, Map<TypeMask, TypeMask>>() {
     unknownConcreteType = new ConcreteType.unknown();
   }
@@ -760,7 +760,7 @@
   /**
    * Returns all the members with name [methodName].
    */
-  List<Element> getMembersByName(SourceString methodName) {
+  List<Element> getMembersByName(String methodName) {
     // TODO(polux): memoize?
     var result = new List<Element>();
     for (ClassElement cls in seenClasses) {
@@ -892,7 +892,7 @@
   /**
    * Add [caller] to the set of [callee]'s dynamic callers.
    */
-  void addDynamicCaller(SourceString callee, FunctionElement caller) {
+  void addDynamicCaller(String callee, FunctionElement caller) {
     Set<FunctionElement> current = dynamicCallers[callee];
     if (current != null) {
       current.add(caller);
@@ -1159,8 +1159,8 @@
     if (signature.optionalParametersAreNamed) {
       // we build a map out of the remaining named parameters
       Link<Element> remainingOptionalParameters = signature.optionalParameters;
-      final Map<SourceString, Element> leftOverNamedParameters =
-          new Map<SourceString, Element>();
+      final Map<String, Element> leftOverNamedParameters =
+          new Map<String, Element>();
       for (;
            !remainingOptionalParameters.isEmpty;
            remainingOptionalParameters = remainingOptionalParameters.tail) {
@@ -1171,7 +1171,7 @@
       // parameters
       for (Identifier identifier in argumentsTypes.named.keys) {
         final ConcreteType concreteType = argumentsTypes.named[identifier];
-        SourceString source = identifier.source;
+        String source = identifier.source;
         final Element namedParameter = leftOverNamedParameters[source];
         // unexisting or already used named parameter
         if (namedParameter == null) return null;
@@ -1303,12 +1303,10 @@
     if (baseType != null && baseType.isClass()) {
       ClassBaseType classBaseType = baseType;
       ClassElement cls = classBaseType.element;
-      SourceString name = function.name;
+      String name = function.name;
       if ((cls == baseTypes.intBaseType.element
           || cls == baseTypes.doubleBaseType.element)
-          && (name == const SourceString('+')
-              || name == const SourceString('-')
-              || name == const SourceString('*'))) {
+          && (name == '+' || name == '-' || name == '*')) {
         Link<Element> parameters =
             function.functionSignature.requiredParameters;
         ConcreteType argumentType = environment.lookupType(parameters.head);
@@ -1495,20 +1493,18 @@
   void initialize() {
     baseTypes = new BaseTypes(compiler);
     ClassElement jsArrayClass = baseTypes.listBaseType.element;
-    listIndex = jsArrayClass.lookupMember(const SourceString('[]'));
-    listIndexSet = jsArrayClass.lookupMember(const SourceString('[]='));
-    listAdd = jsArrayClass.lookupMember(const SourceString('add'));
-    listRemoveAt = jsArrayClass.lookupMember(const SourceString('removeAt'));
-    listInsert = jsArrayClass.lookupMember(const SourceString('insert'));
+    listIndex = jsArrayClass.lookupMember('[]');
+    listIndexSet = jsArrayClass.lookupMember('[]=');
+    listAdd = jsArrayClass.lookupMember('add');
+    listRemoveAt = jsArrayClass.lookupMember('removeAt');
+    listInsert = jsArrayClass.lookupMember('insert');
     listRemoveLast =
-        jsArrayClass.lookupMember(const SourceString('removeLast'));
-    List<SourceString> typePreservingOps = const [const SourceString('+'),
-                                                  const SourceString('-'),
-                                                  const SourceString('*')];
+        jsArrayClass.lookupMember('removeLast');
+    List<String> typePreservingOps = const ['+', '-', '*'];
     listConstructor =
         compiler.listClass.lookupConstructor(
             new Selector.callConstructor(
-                const SourceString(''),
+                '',
                 compiler.listClass.getLibrary())).implementation;
     emptyConcreteType = new ConcreteType.empty(compiler.maxConcreteTypeSize,
                                                baseTypes);
@@ -1581,7 +1577,7 @@
   void debug() {
     print("seen classes:");
     for (ClassElement cls in seenClasses) {
-      print("  ${cls.name.slowToString()}");
+      print("  ${cls.name}");
     }
     print("callers:");
     callers.forEach((k,v) {
@@ -1856,7 +1852,7 @@
 
   ConcreteType analyzeSetNode(Selector selector,
                               Node receiver, ConcreteType argumentType,
-                              SourceString name) {
+                              String name) {
     ConcreteType receiverType = analyze(receiver);
 
     void augmentField(ClassElement receiverType, Element member) {
@@ -1897,35 +1893,34 @@
     return argumentType;
   }
 
-  SourceString canonicalizeCompoundOperator(SourceString op) {
+  String canonicalizeCompoundOperator(String op) {
     // TODO(ahe): This class should work on elements or selectors, not
     // names.  Otherwise, it is repeating work the resolver has
     // already done (or should have done).  In this case, the problem
     // is that the resolver is not recording the selectors it is
     // registering in registerBinaryOperator in
     // ResolverVisitor.visitSendSet.
-    String stringValue = op.stringValue;
-    if (stringValue == '++') return const SourceString(r'+');
-    else if (stringValue == '--') return const SourceString(r'-');
+    if (op == '++') return '+';
+    else if (op == '--') return '-';
     else return Elements.mapToUserOperatorOrNull(op);
   }
 
   ConcreteType visitSendSet(SendSet node) {
     // Operator []= has a different behaviour than other send sets: it is
     // actually a send whose return type is that of its second argument.
-    if (node.selector.asIdentifier().source.stringValue == '[]') {
+    if (node.selector.asIdentifier().source == '[]') {
       ConcreteType receiverType = analyze(node.receiver);
       ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
       analyzeDynamicSend(elements.getSelector(node), receiverType,
-                         const SourceString('[]='), argumentsTypes);
+                         '[]=', argumentsTypes);
       return argumentsTypes.positional[1];
     }
 
     // All other operators have a single argument (++ and -- have an implicit
     // argument: 1). We will store its type in argumentType.
     ConcreteType argumentType;
-    SourceString operatorName = node.assignmentOperator.source;
-    SourceString compoundOperatorName =
+    String operatorName = node.assignmentOperator.source;
+    String compoundOperatorName =
         canonicalizeCompoundOperator(node.assignmentOperator.source);
     // ++, --, +=, -=, ...
     if (compoundOperatorName != null) {
@@ -1934,8 +1929,7 @@
       // argumentsTypes is either computed from the actual arguments or [{int}]
       // in case of ++ or --.
       ArgumentsTypes argumentsTypes;
-      if (operatorName.stringValue == '++'
-          || operatorName.stringValue == '--') {
+      if (operatorName == '++' || operatorName == '--') {
         List<ConcreteType> positionalArguments = <ConcreteType>[
             inferrer.singletonConcreteType(inferrer.baseTypes.intBaseType)];
         argumentsTypes = new ArgumentsTypes(positionalArguments, new Map());
@@ -2134,7 +2128,7 @@
       analyzeDynamicSend(
           elements.getMoveNextSelector(node),
           iteratorType,
-          const SourceString("moveNext"),
+          "moveNext",
           new ArgumentsTypes(const [], const {}));
       // id = n0.current
       ConcreteType currentType = analyzeDynamicGetterSend(
@@ -2199,9 +2193,9 @@
   }
 
   ConcreteType visitOperatorSend(Send node) {
-    SourceString name =
+    String name =
         canonicalizeMethodName(node.selector.asIdentifier().source);
-    if (name == const SourceString('is')) {
+    if (name == 'is') {
       return inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
     }
     return visitDynamicSend(node);
@@ -2297,7 +2291,7 @@
 
   ConcreteType analyzeDynamicSend(Selector selector,
                                   ConcreteType receiverType,
-                                  SourceString canonicalizedMethodName,
+                                  String canonicalizedMethodName,
                                   ArgumentsTypes argumentsTypes) {
     ConcreteType result = inferrer.emptyConcreteType;
 
@@ -2335,10 +2329,9 @@
     return result;
   }
 
-  SourceString canonicalizeMethodName(SourceString name) {
+  String canonicalizeMethodName(String name) {
     // TODO(polux): handle unary-
-    SourceString operatorName =
-        Elements.constructOperatorNameOrNull(name, false);
+    String operatorName = Elements.constructOperatorNameOrNull(name, false);
     if (operatorName != null) return operatorName;
     return name;
   }
@@ -2347,18 +2340,17 @@
     ConcreteType receiverType = (node.receiver != null)
         ? analyze(node.receiver)
         : environment.lookupTypeOfThis();
-    SourceString name =
-        canonicalizeMethodName(node.selector.asIdentifier().source);
-    if (name.stringValue == '!=') {
+    String name = canonicalizeMethodName(node.selector.asIdentifier().source);
+    if (name == '!=') {
       ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
       ConcreteType returnType = analyzeDynamicSend(elements.getSelector(node),
                                                    receiverType,
-                                                   const SourceString('=='),
+                                                   '==',
                                                    argumentsTypes);
       return returnType.isEmpty()
           ? returnType
           : inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
-    } else if (name.stringValue == '&&' || name.stringValue == '||'){
+    } else if (name == '&&' || name == '||') {
       ConcreteTypesEnvironment oldEnvironment = environment;
       analyze(node.arguments.head);
       environment = oldEnvironment.join(environment);
@@ -2383,7 +2375,7 @@
   }
 
   ConcreteType visitStaticSend(Send node) {
-    if (elements.getSelector(node).name == const SourceString('JS')) {
+    if (elements.getSelector(node).name == 'JS') {
       return inferrer.getNativeCallReturnType(node);
     }
     Element element = elements[node].implementation;
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 cc17100..8848fb9 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -563,7 +563,7 @@
     if (isExact) buffer.write('exact=');
     if (isSubclass) buffer.write('subclass=');
     if (isSubtype) buffer.write('subtype=');
-    buffer.write(base.name.slowToString());
+    buffer.write(base.name);
     return "[$buffer]";
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
index d5f8784..522ff2b 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
@@ -9,17 +9,17 @@
 // name -- something like ElementSet seems a bit too generic.
 class FunctionSet {
   final Compiler compiler;
-  final Map<SourceString, FunctionSetNode> nodes =
-      new Map<SourceString, FunctionSetNode>();
+  final Map<String, FunctionSetNode> nodes =
+      new Map<String, FunctionSetNode>();
   FunctionSet(this.compiler);
 
-  FunctionSetNode newNode(SourceString name)
+  FunctionSetNode newNode(String name)
       => new FunctionSetNode(name);
 
   void add(Element element) {
     assert(element.isInstanceMember());
     assert(!element.isAbstract(compiler));
-    SourceString name = element.name;
+    String name = element.name;
     FunctionSetNode node = nodes.putIfAbsent(name, () => newNode(name));
     node.add(element);
   }
@@ -27,7 +27,7 @@
   void remove(Element element) {
     assert(element.isInstanceMember());
     assert(!element.isAbstract(compiler));
-    SourceString name = element.name;
+    String name = element.name;
     FunctionSetNode node = nodes[name];
     if (node != null) {
       node.remove(element);
@@ -37,7 +37,7 @@
   bool contains(Element element) {
     assert(element.isInstanceMember());
     assert(!element.isAbstract(compiler));
-    SourceString name = element.name;
+    String name = element.name;
     FunctionSetNode node = nodes[name];
     return (node != null)
         ? node.contains(element)
@@ -57,7 +57,7 @@
   }
 
   FunctionSetQuery query(Selector selector) {
-    SourceString name = selector.name;
+    String name = selector.name;
     FunctionSetNode node = nodes[name];
     FunctionSetNode noSuchMethods = nodes[Compiler.NO_SUCH_METHOD];
     if (node != null) {
@@ -74,7 +74,7 @@
   }
 
   void forEach(Function action) {
-    nodes.forEach((SourceString name, FunctionSetNode node) {
+    nodes.forEach((String name, FunctionSetNode node) {
       node.forEach(action);
     });
   }
@@ -82,7 +82,7 @@
 
 
 class FunctionSetNode {
-  final SourceString name;
+  final String name;
   final Map<Selector, FunctionSetQuery> cache =
       new Map<Selector, FunctionSetQuery>();
 
@@ -155,14 +155,14 @@
     assert(selector.name == name);
     FunctionSetQuery result = cache[selector];
     if (result != null) return result;
-    Set<Element> functions;
+    Setlet<Element> functions;
     for (Element element in elements) {
       if (selector.appliesUnnamed(element, compiler)) {
         if (functions == null) {
           // Defer the allocation of the functions set until we are
           // sure we need it. This allows us to return immutable empty
           // lists when the filtering produced no results.
-          functions = new Set<Element>();
+          functions = new Setlet<Element>();
         }
         functions.add(element);
       }
@@ -180,7 +180,7 @@
           null);
       if (!noSuchMethodQuery.functions.isEmpty) {
         if (functions == null) {
-          functions = new Set<Element>.from(noSuchMethodQuery.functions);
+          functions = new Setlet<Element>.from(noSuchMethodQuery.functions);
         } else {
           functions.addAll(noSuchMethodQuery.functions);
         }
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index e0b1548..8470f83 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -21,64 +21,55 @@
    * Invariant: Elements are declaration elements.
    */
   // TODO(karlklose): these sets should be merged.
-  final Set<ClassElement> instantiatedClasses;
-  final Set<DartType> instantiatedTypes;
+  final Set<ClassElement> instantiatedClasses = new Set<ClassElement>();
+  final Set<DartType> instantiatedTypes = new Set<DartType>();
 
   /**
    * Documentation wanted -- johnniwinther
    *
    * Invariant: Elements are declaration elements.
    */
-  final Set<FunctionElement> staticFunctionsNeedingGetter;
-  final Map<SourceString, Set<Selector>> invokedNames;
-  final Map<SourceString, Set<Selector>> invokedGetters;
-  final Map<SourceString, Set<Selector>> invokedSetters;
+  final Set<FunctionElement> staticFunctionsNeedingGetter =
+      new Set<FunctionElement>();
+  final Map<String, Set<Selector>> invokedNames =
+      new Map<String, Set<Selector>>();
+  final Map<String, Set<Selector>> invokedGetters =
+      new Map<String, Set<Selector>>();
+  final Map<String, Set<Selector>> invokedSetters =
+      new Map<String, Set<Selector>>();
 
   /**
    * Fields accessed. Currently only the codegen knows this
    * information. The resolver is too conservative when seeing a
    * getter and only registers an invoked getter.
    */
-  final Set<Element> fieldGetters;
+  final Set<Element> fieldGetters = new Set<Element>();
 
   /**
    * Fields set. See comment in [fieldGetters].
    */
-  final Set<Element> fieldSetters;
-  final Set<DartType> isChecks;
+  final Set<Element> fieldSetters = new Set<Element>();
+  final Set<DartType> isChecks = new Set<DartType>();
 
   /**
    * Set of [:call:] methods in instantiated classes that use type variables
    * in their signature.
    */
-  final Set<Element> genericCallMethods;
+  final Set<Element> genericCallMethods = new Set<Element>();
 
   /**
    * Set of closures that use type variables in their signature.
    */
-  final Set<Element> genericClosures;
+  final Set<Element> genericClosures = new Set<Element>();
 
   /**
    * Set of methods in instantiated classes that are potentially
    * closurized.
    */
-  final Set<Element> closurizedMembers;
+  final Set<Element> closurizedMembers = new Set<Element>();
 
   bool usingFactoryWithTypeArguments = false;
 
-  Universe() : instantiatedClasses = new Set<ClassElement>(),
-               instantiatedTypes = new Set<DartType>(),
-               staticFunctionsNeedingGetter = new Set<FunctionElement>(),
-               invokedNames = new Map<SourceString, Set<Selector>>(),
-               invokedGetters = new Map<SourceString, Set<Selector>>(),
-               invokedSetters = new Map<SourceString, Set<Selector>>(),
-               fieldGetters = new Set<Element>(),
-               fieldSetters = new Set<Element>(),
-               isChecks = new Set<DartType>(),
-               genericCallMethods = new Set<Element>(),
-               genericClosures = new Set<Element>(),
-               closurizedMembers = new Set<Element>();
-
   bool hasMatchingSelector(Set<Selector> selectors,
                            Element member,
                            Compiler compiler) {
@@ -135,18 +126,18 @@
 
 class Selector {
   final SelectorKind kind;
-  final SourceString name;
+  final String name;
   final LibraryElement library; // Library is null for non-private selectors.
 
   // The numbers of arguments of the selector. Includes named arguments.
   final int argumentCount;
-  final List<SourceString> namedArguments;
-  final List<SourceString> orderedNamedArguments;
+  final List<String> namedArguments;
+  final List<String> orderedNamedArguments;
   final int hashCode;
 
-  static const SourceString INDEX_NAME = const SourceString("[]");
-  static const SourceString INDEX_SET_NAME = const SourceString("[]=");
-  static const SourceString CALL_NAME = Compiler.CALL_OPERATOR_NAME;
+  static const String INDEX_NAME ="[]";
+  static const String INDEX_SET_NAME = "[]=";
+  static const String CALL_NAME = Compiler.CALL_OPERATOR_NAME;
 
   Selector.internal(this.kind,
                     this.name,
@@ -164,19 +155,19 @@
            || kind == SelectorKind.GETTER
            || kind == SelectorKind.SETTER
            || Elements.operatorNameToIdentifier(name) != name);
-    assert(!name.isPrivate() || library != null);
+    assert(!isPrivateName(name) || library != null);
   }
 
   static Map<int, List<Selector>> canonicalizedValues =
       new Map<int, List<Selector>>();
 
   factory Selector(SelectorKind kind,
-                   SourceString name,
+                   String name,
                    LibraryElement library,
                    int argumentCount,
-                   [List<SourceString> namedArguments]) {
-    if (!name.isPrivate()) library = null;
-    if (namedArguments == null) namedArguments = const <SourceString>[];
+                   [List<String> namedArguments]) {
+    if (!isPrivateName(name)) library = null;
+    if (namedArguments == null) namedArguments = const <String>[];
     int hashCode = computeHashCode(
         kind, name, library, argumentCount, namedArguments);
     List<Selector> list = canonicalizedValues.putIfAbsent(hashCode,
@@ -189,9 +180,9 @@
         return existing;
       }
     }
-    List<SourceString> orderedNamedArguments = namedArguments.isEmpty
-        ? const <SourceString>[]
-        : <SourceString>[];
+    List<String> orderedNamedArguments = namedArguments.isEmpty
+        ? const <String>[]
+        : <String>[];
     Selector result = new Selector.internal(
         kind, name, library, argumentCount,
         namedArguments, orderedNamedArguments,
@@ -201,12 +192,12 @@
   }
 
   factory Selector.fromElement(Element element, Compiler compiler) {
-    SourceString name = element.name;
+    String name = element.name;
     if (element.isFunction()) {
       int arity = element.asFunctionElement().requiredParameterCount(compiler);
-      if (name == const SourceString('[]')) {
+      if (name == '[]') {
         return new Selector.index();
-      } else if (name == const SourceString('[]=')) {
+      } else if (name == '[]=') {
         return new Selector.indexSet();
       } else if (Elements.operatorNameToIdentifier(name) != name) {
         return new Selector(SelectorKind.OPERATOR, name, null, arity);
@@ -222,21 +213,21 @@
     }
   }
 
-  factory Selector.getter(SourceString name, LibraryElement library)
+  factory Selector.getter(String name, LibraryElement library)
       => new Selector(SelectorKind.GETTER, name, library, 0);
 
   factory Selector.getterFrom(Selector selector)
       => new Selector(SelectorKind.GETTER, selector.name, selector.library, 0);
 
-  factory Selector.setter(SourceString name, LibraryElement library)
+  factory Selector.setter(String name, LibraryElement library)
       => new Selector(SelectorKind.SETTER, name, library, 1);
 
-  factory Selector.unaryOperator(SourceString name)
+  factory Selector.unaryOperator(String name)
       => new Selector(SelectorKind.OPERATOR,
                       Elements.constructOperatorName(name, true),
                       null, 0);
 
-  factory Selector.binaryOperator(SourceString name)
+  factory Selector.binaryOperator(String name)
       => new Selector(SelectorKind.OPERATOR,
                       Elements.constructOperatorName(name, false),
                       null, 1);
@@ -251,13 +242,13 @@
                       Elements.constructOperatorName(INDEX_SET_NAME, false),
                       null, 2);
 
-  factory Selector.call(SourceString name,
+  factory Selector.call(String name,
                         LibraryElement library,
                         int arity,
-                        [List<SourceString> namedArguments])
+                        [List<String> namedArguments])
       => new Selector(SelectorKind.CALL, name, library, arity, namedArguments);
 
-  factory Selector.callClosure(int arity, [List<SourceString> namedArguments])
+  factory Selector.callClosure(int arity, [List<String> namedArguments])
       => new Selector(SelectorKind.CALL, CALL_NAME, null,
                       arity, namedArguments);
 
@@ -265,20 +256,20 @@
       => new Selector(SelectorKind.CALL, CALL_NAME, null,
                       selector.argumentCount, selector.namedArguments);
 
-  factory Selector.callConstructor(SourceString name, LibraryElement library,
+  factory Selector.callConstructor(String name, LibraryElement library,
                                    [int arity = 0,
-                                    List<SourceString> namedArguments])
+                                    List<String> namedArguments])
       => new Selector(SelectorKind.CALL, name, library,
                       arity, namedArguments);
 
   factory Selector.callDefaultConstructor(LibraryElement library)
-      => new Selector(SelectorKind.CALL, const SourceString(""), library, 0);
+      => new Selector(SelectorKind.CALL, "", library, 0);
 
   bool isGetter() => identical(kind, SelectorKind.GETTER);
   bool isSetter() => identical(kind, SelectorKind.SETTER);
   bool isCall() => identical(kind, SelectorKind.CALL);
   bool isClosureCall() {
-    SourceString callName = Compiler.CALL_OPERATOR_NAME;
+    String callName = Compiler.CALL_OPERATOR_NAME;
     return isCall() && name == callName;
   }
 
@@ -290,7 +281,7 @@
   bool isBinaryOperator() => isOperator() && argumentCount == 1;
 
   /** Check whether this is a call to 'assert'. */
-  bool isAssert() => isCall() && identical(name.stringValue, "assert");
+  bool isAssert() => isCall() && identical(name, "assert");
 
   int get namedArgumentCount => namedArguments.length;
   int get positionalArgumentCount => argumentCount - namedArgumentCount;
@@ -303,7 +294,7 @@
    * The member name for invocation mirrors created from this selector.
    */
   String get invocationMirrorMemberName =>
-      isSetter() ? '${name.slowToString()}=' : name.slowToString();
+      isSetter() ? '$name=' : name;
 
   int get invocationMirrorKind {
     const int METHOD = 0;
@@ -326,7 +317,7 @@
   bool appliesUntyped(Element element, Compiler compiler) {
     assert(sameNameHack(element, compiler));
     if (Elements.isUnresolved(element)) return false;
-    if (name.isPrivate() && library != element.getLibrary()) return false;
+    if (isPrivateName(name) && library != element.getLibrary()) return false;
     if (element.isForeign(compiler)) return true;
     if (element.isSetter()) return isSetter();
     if (element.isGetter()) return isGetter() || isCall();
@@ -356,11 +347,11 @@
       if (positionalArgumentCount > requiredParameterCount) return false;
       assert(positionalArgumentCount == requiredParameterCount);
       if (namedArgumentCount > optionalParameterCount) return false;
-      Set<SourceString> nameSet = new Set<SourceString>();
+      Set<String> nameSet = new Set<String>();
       parameters.optionalParameters.forEach((Element element) {
         nameSet.add(element.name);
       });
-      for (SourceString name in namedArguments) {
+      for (String name in namedArguments) {
         if (!nameSet.contains(name)) return false;
         // TODO(5213): By removing from the set we are checking
         // that we are not passing the name twice. We should have this
@@ -498,7 +489,7 @@
 
     // Synthesize a selector for the call.
     // TODO(ngeoffray): Should the resolver do it instead?
-    List<SourceString> namedParameters;
+    List<String> namedParameters;
     if (signature.optionalParametersAreNamed) {
       namedParameters =
           signature.optionalParameters.toList().map((e) => e.name).toList();
@@ -516,7 +507,7 @@
                                        compiler);
   }
 
-  static bool sameNames(List<SourceString> first, List<SourceString> second) {
+  static bool sameNames(List<String> first, List<String> second) {
     for (int i = 0; i < first.length; i++) {
       if (first[i] != second[i]) return false;
     }
@@ -524,10 +515,10 @@
   }
 
   bool match(SelectorKind kind,
-             SourceString name,
+             String name,
              LibraryElement library,
              int argumentCount,
-             List<SourceString> namedArguments) {
+             List<String> namedArguments) {
     return this.kind == kind
         && this.name == name
         && identical(this.library, library)
@@ -537,10 +528,10 @@
   }
 
   static int computeHashCode(SelectorKind kind,
-                             SourceString name,
+                             String name,
                              LibraryElement library,
                              int argumentCount,
-                             List<SourceString> namedArguments) {
+                             List<String> namedArguments) {
     // Add bits from name and kind.
     int hash = mixHashCodeBits(name.hashCode, kind.hashCode);
     // Add bits from the library.
@@ -573,13 +564,13 @@
     return (high * 13) ^ (low * 997) ^ h;
   }
 
-  List<SourceString> getOrderedNamedArguments() {
+  List<String> getOrderedNamedArguments() {
     if (namedArguments.isEmpty) return namedArguments;
     if (!orderedNamedArguments.isEmpty) return orderedNamedArguments;
 
     orderedNamedArguments.addAll(namedArguments);
-    orderedNamedArguments.sort((SourceString first, SourceString second) {
-      return first.slowToString().compareTo(second.slowToString());
+    orderedNamedArguments.sort((String first, String second) {
+      return first.compareTo(second);
     });
     return orderedNamedArguments;
   }
@@ -589,7 +580,7 @@
       StringBuffer result = new StringBuffer();
       for (int i = 0; i < namedArgumentCount; i++) {
         if (i != 0) result.write(', ');
-        result.write(namedArguments[i].slowToString());
+        result.write(namedArguments[i]);
       }
       return "[$result]";
     }
@@ -601,7 +592,7 @@
     String type = '';
     if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}';
     if (mask != null) type = ', mask=$mask';
-    return 'Selector($kind, ${name.slowToString()}, '
+    return 'Selector($kind, $name, '
            'arity=$argumentCount$named$type)';
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/util/setlet.dart b/sdk/lib/_internal/compiler/implementation/util/setlet.dart
new file mode 100644
index 0000000..abece72
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/util/setlet.dart
@@ -0,0 +1,225 @@
+// 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 dart2js.util.setlet;
+
+import 'dart:collection' show IterableBase;
+
+class Setlet<E> extends IterableBase<E> {
+  static const _MARKER = const _SetletMarker();
+  static const CAPACITY = 8;
+
+  // The setlet can be in one of four states:
+  //
+  //   * Empty          (extra: null,   contents: marker)
+  //   * Single element (extra: null,   contents: element)
+  //   * List-backed    (extra: length, contents: list)
+  //   * Set-backed     (extra: marker, contents: set)
+  //
+  // When the setlet is list-backed, the list in the contents field
+  // may have empty slots filled with the marker value.
+  var _contents = _MARKER;
+  var _extra;
+
+  Setlet();
+  Setlet.from(Iterable<E> elements) {
+    addAll(elements);
+  }
+
+  Iterator<E> get iterator {
+    if (_extra == null) {
+      return new _SetletSingleIterator<E>(_contents);
+    } else if (_MARKER == _extra) {
+      return _contents.iterator;
+    } else {
+      return new _SetletListIterator<E>(_contents, _extra);
+    }
+  }
+
+  int get length {
+    if (_extra == null) {
+      return (_MARKER == _contents) ? 0 : 1;
+    } else if (_MARKER == _extra) {
+      return _contents.length;
+    } else {
+      return _extra;
+    }
+  }
+
+  bool get isEmpty {
+    if (_extra == null) {
+      return _MARKER == _contents;
+    } else if (_MARKER == _extra) {
+      return _contents.isEmpty;
+    } else {
+      return _extra == 0;
+    }
+  }
+
+  bool contains(E element) {
+    if (_extra == null) {
+      return _contents == element;
+    } else if (_MARKER == _extra) {
+      return _contents.contains(element);
+    } else {
+      for (int remaining = _extra, i = 0; remaining > 0 && i < CAPACITY; i++) {
+        var candidate = _contents[i];
+        if (_MARKER == candidate) continue;
+        if (candidate == element) return true;
+        remaining--;
+      }
+      return false;
+    }
+  }
+
+  bool remove(E element) {
+    if (_extra == null) {
+      if (_contents == element) {
+        _contents = _MARKER;
+        return true;
+      } else {
+        return false;
+      }
+    } else if (_MARKER == _extra) {
+      return _contents.remove(element);
+    } else {
+      for (int remaining = _extra, i = 0; remaining > 0 && i < CAPACITY; i++) {
+        var candidate = _contents[i];
+        if (_MARKER == candidate) continue;
+        if (candidate == element) {
+          _contents[i] = _MARKER;
+          _extra--;
+          return true;
+        }
+        remaining--;
+      }
+      return false;
+    }
+  }
+
+  void add(E element) {
+    if (_extra == null) {
+      if (_MARKER == _contents) {
+        _contents = element;
+      } else if (_contents == element) {
+        // Do nothing.
+      } else {
+        List list = new List(CAPACITY);
+        list[0] = _contents;
+        list[1] = element;
+        _contents = list;
+        _extra = 2;  // Two elements.
+      }
+    } else if (_MARKER == _extra) {
+      _contents.add(element);
+    } else {
+      int remaining = _extra;
+      int index = 0;
+      int copyTo, copyFrom;
+      while (remaining > 0 && index < CAPACITY) {
+        var candidate = _contents[index++];
+        if (_MARKER == candidate) {
+          // Keep track of the last range of empty slots in the
+          // list. When we're done we'll move all the elements
+          // after those empty slots down, so that adding an element
+          // after that will preserve the insertion order.
+          if (copyFrom == index - 1) {
+            copyFrom++;
+          } else {
+            copyTo = index - 1;
+            copyFrom = index;
+          }
+          continue;
+        } else if (candidate == element) {
+          return;
+        }
+        remaining--;
+      }
+      if (index < CAPACITY) {
+        _contents[index] = element;
+        _extra++;
+      } else if (_extra < CAPACITY) {
+        // Move the last elements down into the last empty slots
+        // so that we have empty slots after the last element.
+        while (copyFrom < CAPACITY) {
+          _contents[copyTo++] = _contents[copyFrom++];
+        }
+        // Insert the new element as the last element.
+        _contents[copyTo++] = element;
+        _extra++;
+        // Clear all elements after the new last elements to
+        // make sure we don't keep extra stuff alive.
+        while (copyTo < CAPACITY) _contents[copyTo++] = null;
+      } else {
+        _contents = new Set<E>()..addAll(_contents)..add(element);
+        _extra = _MARKER;
+      }
+    }
+  }
+
+  void addAll(Iterable<E> elements) {
+    elements.forEach((each) => add(each));
+  }
+
+  void forEach(void action(E element)) {
+    if (_extra == null) {
+      if (_MARKER != _contents) action(_contents);
+    } else if (_MARKER == _extra) {
+      _contents.forEach(action);
+    } else {
+      for (int remaining = _extra, i = 0; remaining > 0 && i < CAPACITY; i++) {
+        var element = _contents[i];
+        if (_MARKER == element) continue;
+        action(element);
+        remaining--;
+      }
+    }
+  }
+}
+
+class _SetletMarker {
+  const _SetletMarker();
+  toString() => "-";
+}
+
+class _SetletSingleIterator<E> implements Iterator<E> {
+  var _element;
+  E _current;
+  _SetletSingleIterator(this._element);
+
+  E get current => _current;
+
+  bool moveNext() {
+    if (Setlet._MARKER == _element) {
+      _current = null;
+      return false;
+    }
+    _current = _element;
+    _element = Setlet._MARKER;
+    return true;
+  }
+}
+
+class _SetletListIterator<E> implements Iterator<E> {
+  final List _list;
+  int _remaining;
+  int _index = 0;
+  E _current;
+  _SetletListIterator(this._list, this._remaining);
+
+  E get current => _current;
+
+  bool moveNext() {
+    while (_remaining > 0) {
+      var candidate = _list[_index++];
+      if (Setlet._MARKER != candidate) {
+        _current = candidate;
+        _remaining--;
+        return true;
+      }
+    }
+    _current = null;
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/compiler/implementation/util/util.dart b/sdk/lib/_internal/compiler/implementation/util/util.dart
index c904cc1..dee467d 100644
--- a/sdk/lib/_internal/compiler/implementation/util/util.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/util.dart
@@ -8,6 +8,8 @@
 import 'util_implementation.dart';
 import 'characters.dart';
 
+export 'setlet.dart';
+
 part 'link.dart';
 part 'expensive_map.dart';
 part 'expensive_set.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 6bde7b8..45803c19 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -289,7 +289,37 @@
 """
 library type;
 
-class Type {}"""}]);
+class Type {}"""},
+          const {
+'conflictsWithDart.dart':
+"""
+library conflictsWithDart;
+
+class Duration {
+  static var x = 100;
+}
+""",
+
+'conflictsWithDartAsWell.dart':
+"""
+library conflictsWithDartAsWell;
+
+class Duration {
+  static var x = 100;
+}
+""",
+
+'main.dart':
+r"""
+library testDartConflicts;
+
+import 'conflictsWithDart.dart';
+import 'conflictsWithDartAsWell.dart';
+
+main() {
+  print("Hail Caesar ${Duration.x}");
+}
+"""}]);
 
   static const MessageKind DUPLICATE_EXPORT = const MessageKind(
       "Error: Duplicate export of '#{name}'.",
@@ -700,10 +730,6 @@
 typedef H(F f); // The argument type 'F' creates a self-reference.
 main() { F f = null; }"""]);
 
-  static const CYCLIC_TYPEDEF_TYPEVAR = const MessageKind(
-      "Internal Error: Recursive type variable bounds are not "
-      "supported on typedefs.");
-
   static const MessageKind CLASS_NAME_EXPECTED = const MessageKind(
       "Error: Class name expected.");
 
@@ -1284,6 +1310,41 @@
   below as well as the source location above).
 ''');
 
+  static const MessageKind POTENTIAL_MUTATION = const MessageKind(
+      "Hint: Variable '#{variableName}' is not known to be of type "
+      "'#{shownType}' because it is potentially mutated in the scope for "
+      "promotion.");
+
+  static const MessageKind POTENTIAL_MUTATION_HERE = const MessageKind(
+      "Info: Variable '#{variableName}' is potentially mutated here.");
+
+  static const MessageKind POTENTIAL_MUTATION_IN_CLOSURE = const MessageKind(
+      "Hint: Variable '#{variableName}' is not known to be of type "
+      "'#{shownType}' because it is potentially mutated within a closure.");
+
+  static const MessageKind POTENTIAL_MUTATION_IN_CLOSURE_HERE =
+      const MessageKind(
+          "Info: Variable '#{variableName}' is potentially mutated in a "
+          "closure here.");
+
+  static const MessageKind ACCESSED_IN_CLOSURE = const MessageKind(
+      "Hint: Variable '#{variableName}' is not known to be of type "
+      "'#{shownType}' because it is accessed by a closure in the scope for "
+      "promotion and potentially mutated in the scope of '#{variableName}'.");
+
+  static const MessageKind ACCESSED_IN_CLOSURE_HERE = const MessageKind(
+      "Info: Variable '#{variableName}' is accessed in a closure here.");
+
+  static const MessageKind NOT_MORE_SPECIFIC = 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}'.");
+
+  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.
@@ -1412,8 +1473,7 @@
     if (message == null) {
       message = kind.template;
       arguments.forEach((key, value) {
-        String string = slowToString(value);
-        message = message.replaceAll('#{${key}}', string);
+        message = message.replaceAll('#{${key}}', value.toString());
       });
       assert(invariant(
           CURRENT_ELEMENT_SPANNABLE,
@@ -1422,8 +1482,7 @@
       if (!terse && kind.hasHowToFix) {
         String howToFix = kind.howToFix;
         arguments.forEach((key, value) {
-          String string = slowToString(value);
-          howToFix = howToFix.replaceAll('#{${key}}', string);
+          howToFix = howToFix.replaceAll('#{${key}}', value.toString());
         });
         message = '$message\n$howToFix';
       }
@@ -1441,14 +1500,6 @@
   }
 
   int get hashCode => throw new UnsupportedError('Message.hashCode');
-
-  String slowToString(object) {
-    if (object is SourceString) {
-      return object.slowToString();
-    } else {
-      return object.toString();
-    }
-  }
 }
 
 class Diagnostic {
diff --git a/sdk/lib/_internal/compiler/implementation/world.dart b/sdk/lib/_internal/compiler/implementation/world.dart
index 17f3b7f..722688d 100644
--- a/sdk/lib/_internal/compiler/implementation/world.dart
+++ b/sdk/lib/_internal/compiler/implementation/world.dart
@@ -61,7 +61,7 @@
       assert(cls.isDeclaration);
       if (cls.resolutionState != STATE_DONE) {
         compiler.internalErrorOnElement(
-            cls, 'Class "${cls.name.slowToString()}" is not resolved.');
+            cls, 'Class "${cls.name}" is not resolved.');
       }
 
       for (DartType type in cls.allSupertypes) {
diff --git a/sdk/lib/_internal/dartdoc/lib/classify.dart b/sdk/lib/_internal/dartdoc/lib/classify.dart
index 4b4d972..e4ed4db 100644
--- a/sdk/lib/_internal/dartdoc/lib/classify.dart
+++ b/sdk/lib/_internal/dartdoc/lib/classify.dart
@@ -39,7 +39,7 @@
 String classifySource(String text) {
   try {
     var html = new StringBuffer();
-    var tokenizer = new StringScanner(text, includeComments: true);
+    var tokenizer = new StringScanner.fromString(text, includeComments: true);
 
     var whitespaceOffset = 0;
     var token = tokenizer.tokenize();
@@ -57,7 +57,7 @@
       }
 
       final kind = classify(token);
-      final escapedText = md.escapeHtml(token.slowToString());
+      final escapedText = md.escapeHtml(token.value);
       if (kind != null) {
         // Add a secondary class to tokens appearing within a string so that
         // we can highlight tokens in an interpolation specially.
@@ -101,12 +101,9 @@
 
 String classify(Token token) {
   switch (token.kind) {
-    case UNKNOWN_TOKEN:
-      return Classification.ERROR;
-
     case IDENTIFIER_TOKEN:
       // Special case for names that look like types.
-      final text = token.slowToString();
+      final text = token.value;
       if (_looksLikeType(text)
           || text == 'num'
           || text == 'bool'
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart b/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart
index b591475..7ee8828 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart
@@ -13,7 +13,8 @@
 import '../../../compiler/implementation/mirrors/mirrors.dart'
     show MirrorSystem;
 import '../../../compiler/implementation/source_file_provider.dart'
-    show FormattingDiagnosticHandler, SourceFileProvider;
+    show FormattingDiagnosticHandler, SourceFileProvider,
+         CompilerSourceFileProvider;
 import '../../../compiler/implementation/filenames.dart'
     show appendSlash, currentDirectory;
 
@@ -29,7 +30,7 @@
                        {String packageRoot,
                         List<String> options: const <String>[],
                         api.DiagnosticHandler diagnosticHandler}) {
-  SourceFileProvider provider = new SourceFileProvider();
+  SourceFileProvider provider = new CompilerSourceFileProvider();
   if (diagnosticHandler == null) {
     diagnosticHandler =
         new FormattingDiagnosticHandler(provider).diagnosticHandler;
@@ -53,7 +54,7 @@
                              {String packageRoot,
                               List<String> options: const <String>[],
                               api.DiagnosticHandler diagnosticHandler}) {
-  SourceFileProvider provider = new SourceFileProvider();
+  SourceFileProvider provider = new CompilerSourceFileProvider();
   if (diagnosticHandler == null) {
     diagnosticHandler =
         new FormattingDiagnosticHandler(provider).diagnosticHandler;
diff --git a/sdk/lib/_internal/lib/collection_patch.dart b/sdk/lib/_internal/lib/collection_patch.dart
index 7c1bbf1..e98bac6 100644
--- a/sdk/lib/_internal/lib/collection_patch.dart
+++ b/sdk/lib/_internal/lib/collection_patch.dart
@@ -1002,15 +1002,15 @@
   }
 
   // Collection.
-  void add(E element) {
+  bool add(E element) {
     if (_isStringElement(element)) {
       var strings = _strings;
       if (strings == null) _strings = strings = _newHashTable();
-      _addHashTableEntry(strings, element);
+      return _addHashTableEntry(strings, element);
     } else if (_isNumericElement(element)) {
       var nums = _nums;
       if (nums == null) _nums = nums = _newHashTable();
-      _addHashTableEntry(nums, element);
+      return _addHashTableEntry(nums, element);
     } else {
       var rest = _rest;
       if (rest == null) _rest = rest = _newHashTable();
@@ -1020,11 +1020,12 @@
         _setTableEntry(rest, hash, JS('var', '[#]', element));
       } else {
         int index = _findBucketIndex(bucket, element);
-        if (index >= 0) return;
+        if (index >= 0) return false;
         JS('void', '#.push(#)', bucket, element);
       }
       _length++;
       _elements = null;
+      return true;
     }
   }
 
@@ -1131,11 +1132,12 @@
     return _elements = result;
   }
 
-  void _addHashTableEntry(var table, E element) {
-    if (_hasTableEntry(table, element)) return;
+  bool _addHashTableEntry(var table, E element) {
+    if (_hasTableEntry(table, element)) return false;
     _setTableEntry(table, element, 0);
     _length++;
     _elements = null;
+    return true;
   }
 
   bool _removeHashTableEntry(var table, Object element) {
@@ -1456,15 +1458,15 @@
   }
 
   // Collection.
-  void add(E element) {
+  bool add(E element) {
     if (_isStringElement(element)) {
       var strings = _strings;
       if (strings == null) _strings = strings = _newHashTable();
-      _addHashTableEntry(strings, element);
+      return _addHashTableEntry(strings, element);
     } else if (_isNumericElement(element)) {
       var nums = _nums;
       if (nums == null) _nums = nums = _newHashTable();
-      _addHashTableEntry(nums, element);
+      return _addHashTableEntry(nums, element);
     } else {
       var rest = _rest;
       if (rest == null) _rest = rest = _newHashTable();
@@ -1475,10 +1477,11 @@
         _setTableEntry(rest, hash, JS('var', '[#]', cell));
       } else {
         int index = _findBucketIndex(bucket, element);
-        if (index >= 0) return;
+        if (index >= 0) return false;
         LinkedHashSetCell cell = _newLinkedCell(element);
         JS('void', '#.push(#)', bucket, cell);
       }
+      return true;
     }
   }
 
@@ -1548,10 +1551,11 @@
     }
   }
 
-  void _addHashTableEntry(var table, E element) {
+  bool _addHashTableEntry(var table, E element) {
     LinkedHashSetCell cell = _getTableEntry(table, element);
-    if (cell != null) return;
+    if (cell != null) return false;
     _setTableEntry(table, element, _newLinkedCell(element));
+    return true;
   }
 
   bool _removeHashTableEntry(var table, Object element) {
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 1b68a3a..1c4c70b 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -27,7 +27,8 @@
     getMangledTypeName,
     throwInvalidReflectionError,
     hasReflectableProperty,
-    runtimeTypeToString;
+    runtimeTypeToString,
+    TypeVariable;
 import 'dart:_interceptors' show
     Interceptor,
     JSExtendableArray;
@@ -181,11 +182,13 @@
 }
 
 class JsTypeVariableMirror extends JsTypeMirror implements TypeVariableMirror {
-  final TypeMirror upperBound;
   final DeclarationMirror owner;
+  final TypeVariable _typeVariable;
+  TypeMirror _cachedUpperBound;
 
-  JsTypeVariableMirror(Symbol simpleName, this.upperBound, this.owner)
-      : super(simpleName);
+  JsTypeVariableMirror(TypeVariable typeVariable, this.owner)
+      : this._typeVariable = typeVariable,
+        super(s(typeVariable.name));
 
   bool operator ==(other) {
     return (other is JsTypeVariableMirror &&
@@ -201,6 +204,12 @@
   }
 
   String get _prettyName => 'TypeVariableMirror';
+
+  TypeMirror get upperBound {
+    if (_cachedUpperBound != null) return _cachedUpperBound;
+    return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation(
+        JS('', 'init.metadata[#]', _typeVariable.bound));
+  }
 }
 
 class JsTypeMirror extends JsDeclarationMirror implements TypeMirror {
@@ -451,11 +460,11 @@
   }
 }
 
-ClassMirror reflectType(Type key) {
+TypeMirror reflectType(Type key) {
   return reflectClassByMangledName(getMangledTypeName(key));
 }
 
-ClassMirror reflectClassByMangledName(String mangledName) {
+TypeMirror reflectClassByMangledName(String mangledName) {
   String unmangledName = mangledGlobalNames[mangledName];
   if (unmangledName == null) unmangledName = mangledName;
   return reflectClassByName(s(unmangledName), mangledName);
@@ -463,7 +472,7 @@
 
 var classMirrors;
 
-ClassMirror reflectClassByName(Symbol symbol, String mangledName) {
+TypeMirror reflectClassByName(Symbol symbol, String mangledName) {
   if (classMirrors == null) classMirrors = JsCache.allocate();
   var mirror = JsCache.fetch(classMirrors, mangledName);
   if (mirror != null) return mirror;
@@ -827,6 +836,7 @@
   List<TypeMirror> get typeArguments {
     if (_typeArgs is! String) return _typeArgs;
     List result = new List();
+
     if (_typeArgs.indexOf('<') == -1) {
       for (String s in _typeArgs.split(',')) {
         result.add(reflectClassByMangledName(s.trim()));
@@ -1320,13 +1330,9 @@
    List typeVars =
         JS('JSExtendableArray|Null', '#.prototype["<>"]', _jsConstructor);
     if (typeVars == null) return result;
-    for (int i = 0; i < typeVars.length; i += 2) {
-      TypeMirror upperBound =
-         typeMirrorFromRuntimeTypeRepresentation(JS('', 'init.metadata[#]',
-                                                    typeVars[i+1]));
-      var typeMirror =
-          new JsTypeVariableMirror(s(typeVars[i]), upperBound, this);
-      result.add(typeMirror);
+    for (int i = 0; i < typeVars.length; i++) {
+      TypeVariable typeVariable = JS('', 'init.metadata[#]', typeVars[i]);
+      result.add(new JsTypeVariableMirror(typeVariable, this));
     }
     return _cachedTypeVariables = new UnmodifiableListView(result);
   }
@@ -1701,10 +1707,6 @@
   JsFunctionTypeMirror get value => referent;
 
   String get _prettyName => 'TypedefMirror';
-
-  // TODO(zarah): This method doesn't belong here, since TypedefMirror shouldn't
-  // be a subtype of ClassMirror.
-  ClassMirror get originalDeclaration => this;
 }
 
 class JsFunctionTypeMirror implements FunctionTypeMirror {
diff --git a/sdk/lib/_internal/lib/js_number.dart b/sdk/lib/_internal/lib/js_number.dart
index 8dd89d8..b5591fb 100644
--- a/sdk/lib/_internal/lib/js_number.dart
+++ b/sdk/lib/_internal/lib/js_number.dart
@@ -58,10 +58,11 @@
   num abs() => JS('num', r'Math.abs(#)', this);
 
   int toInt() {
-    if (isNaN) throw new UnsupportedError('NaN');
-    if (isInfinite) throw new UnsupportedError('Infinity');
-    num truncated = truncateToDouble();
-    return JS('bool', r'# == -0.0', truncated) ? 0 : truncated;
+    if (JS('bool', r'isFinite(#)', this)) {
+      return JS('int', r'# + 0', truncateToDouble());  // Converts -0.0 to +0.0.
+    }
+    // This is either NaN, Infinity or -Infinity.
+    throw new UnsupportedError(JS("String", "''+#", this));
   }
 
   int truncate() => toInt();
diff --git a/sdk/lib/_internal/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
index ea01f76..d7c28e0 100644
--- a/sdk/lib/_internal/lib/js_rti.dart
+++ b/sdk/lib/_internal/lib/js_rti.dart
@@ -66,6 +66,20 @@
   }
 }
 
+/**
+ * Represents a type variable.
+ *
+ * This class holds the information needed when reflecting on generic classes
+ * and their members.
+ */
+class TypeVariable {
+  final Type owner;
+  final String name;
+  final int bound;
+
+  const TypeVariable(this.owner, this.name, this.bound);
+}
+
 getMangledTypeName(TypeImpl type) => type._typeName;
 
 /**
diff --git a/sdk/lib/_internal/lib/mirrors_patch.dart b/sdk/lib/_internal/lib/mirrors_patch.dart
index dba0e33..1254791 100644
--- a/sdk/lib/_internal/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/lib/mirrors_patch.dart
@@ -24,7 +24,13 @@
 
 patch ClassMirror reflectClass(Type key) {
   if (key is! Type || key == dynamic) {
-  	throw new ArgumentError('$key does not denote a class');
+    throw new ArgumentError('$key does not denote a class');
   }
-  return js.reflectType(key).originalDeclaration;
+  TypeMirror tm = reflectType(key);
+  if (tm is! ClassMirror) {
+    throw new ArgumentError("$key does not denote a class");
+  }
+  return (tm as ClassMirror).originalDeclaration;
 }
+
+patch TypeMirror reflectType(Type key) => js.reflectType(key);
diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
index 54073c3..bbee3a5 100644
--- a/sdk/lib/_internal/lib/native_helper.dart
+++ b/sdk/lib/_internal/lib/native_helper.dart
@@ -234,96 +234,24 @@
   return JS('bool', '((#) instanceof (#))', obj, JS_DART_OBJECT_CONSTRUCTOR());
 }
 
-/// A JavaScript object mapping tags to interceptors.
-var interceptorsByTag;
-
-/// A JavaScript object mapping tags to `true` or `false`.
-var leafTags;
-
-/// A JavaScript list mapping subclass interceptor constructors to the native
-/// superclass tag.
-var interceptorToTag;
+/**
+ * A JavaScript object mapping tags to the constructors of interceptors.
+ *
+ * Example: 'HTMLImageElement' maps to the ImageElement native class
+ * constructor.
+ */
+get interceptorsByTag => JS('=Object', 'init.interceptorsByTag');
 
 /**
- * Associates dispatch tags (JavaScript constructor names e.g. DOM interface
- * names like HTMLDivElement) with an interceptor.  Called from generated code
- * during initial isolate definition.
+ * A JavaScript object mapping tags to `true` or `false`.
  *
- * The tags are all 'leaf' tags representing classes that have no subclasses
- * with different behaviour.
- *
- * [tags] is a string of `|`-separated tags.
+ * Example: 'HTMLImageElement' maps to `true` since, as since there are no
+ * subclasses of ImageElement, it is a leaf class in the native class hierarchy.
  */
-void defineNativeMethods(String tags, interceptorClass) {
-  defineNativeMethodsCommon(tags, interceptorClass, true);
-}
-
-/**
- * Associates dispatch tags (JavaScript constructor names e.g. DOM interface
- * names like HTMLElement) with an interceptor.  Called from generated code
- * during initial isolate definition.
- *
- * The tags are all non-'leaf' tags, representing classes that have a subclass
- * with different behaviour.
- */
-void defineNativeMethodsNonleaf(String tags, interceptorClass) {
-  defineNativeMethodsCommon(tags, interceptorClass, false);
-}
-
-/**
- * Associates dispatch tags (JavaScript constructor names e.g. DOM interface
- * names like HTMLElement) with an interceptor.  Called from generated code
- * during initial isolate definition.
- *
- * The tags are all non-'leaf' tags, representing classes that have a user
- * defined subclass that requires additional dispatch.
- * [subclassInterceptorClasses] is a list of interceptor classes
- * (i.e. constructors) for the user defined subclasses.
- */
-void defineNativeMethodsExtended(String tags, interceptorClass,
-                                 subclassInterceptorClasses) {
-  if (interceptorToTag == null) {
-    interceptorToTag = [];
-  }
-  List classes = JS('JSFixedArray', '#', subclassInterceptorClasses);
-  for (int i = 0; i < classes.length; i++) {
-    interceptorToTag.add(classes[i]);
-    // 'tags' is a single tag.
-    interceptorToTag.add(tags);
-  }
-
-  defineNativeMethodsCommon(tags, interceptorClass, false);
-}
-
-// TODO(sra): Try to encode all the calls to defineNativeMethodsXXX as pure
-// data.  The challenge is that the calls remove a lot of redundancy that is
-// expanded by the loops in these methods.
-void defineNativeMethodsCommon(String tags, var interceptorClass, bool isLeaf) {
-  var methods = JS('', '#.prototype', interceptorClass);
-  if (interceptorsByTag == null) interceptorsByTag = JS('=Object', '{}');
-  if (leafTags == null) leafTags = JS('=Object', '{}');
-
-  var tagsList = JS('JSExtendableArray', '#.split("|")', tags);
-  for (int i = 0; i < tagsList.length; i++) {
-    var tag = tagsList[i];
-    JS('void', '#[#] = #', interceptorsByTag, tag, methods);
-    JS('void', '#[#] = #', leafTags, tag, isLeaf);
-  }
-}
-
-void defineNativeMethodsFinish() {
-  // TODO(sra): Investigate placing a dispatch record on Object.prototype that
-  // returns an interceptor for JavaScript objects.  This avoids needing a test
-  // in every interceptor, and prioritizes the performance of known native
-  // classes over unknown.
-}
+get leafTags => JS('=Object', 'init.leafTags');
 
 String findDispatchTagForInterceptorClass(interceptorClassConstructor) {
-  if (interceptorToTag == null) return null;
-  int i =
-      JS('int', '#.indexOf(#)', interceptorToTag, interceptorClassConstructor);
-  if (i < 0) return null;
-  return JS('', '#[#]', interceptorToTag, i + 1);
+  return JS('', r'#.$nativeSuperclassTag', interceptorClassConstructor);
 }
 
 lookupInterceptor(var hasOwnPropertyFunction, String tag) {
@@ -336,18 +264,18 @@
 
 lookupDispatchRecord(obj) {
   var hasOwnPropertyFunction = JS('var', 'Object.prototype.hasOwnProperty');
-  var interceptor = null;
+  var interceptorClass = null;
   assert(!isDartObject(obj));
   String tag = getTypeNameOf(obj);
 
-  interceptor = lookupInterceptor(hasOwnPropertyFunction, tag);
-  if (interceptor == null) {
+  interceptorClass = lookupInterceptor(hasOwnPropertyFunction, tag);
+  if (interceptorClass == null) {
     String secondTag = alternateTag(obj, tag);
     if (secondTag != null) {
-      interceptor = lookupInterceptor(hasOwnPropertyFunction, secondTag);
+      interceptorClass = lookupInterceptor(hasOwnPropertyFunction, secondTag);
     }
   }
-  if (interceptor == null) {
+  if (interceptorClass == null) {
     // This object is not known to Dart.  There could be several
     // reasons for that, including (but not limited to):
     // * A bug in native code (hopefully this is caught during development).
@@ -356,6 +284,7 @@
     //   example, on node.js.
     return null;
   }
+  var interceptor = JS('', '#.prototype', interceptorClass);
   var isLeaf =
       (leafTags != null) && JS('bool', '(#[#]) === true', leafTags, tag);
   if (isLeaf) {
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 97d878a..bb51df0 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
@@ -149,7 +149,7 @@
     var sourcePath = path.fromUri(resourceUri);
     return _readResource(resourceUri).then((source) {
       _sourceFiles[resourceUri.toString()] =
-          new SourceFile(path.relative(sourcePath), source);
+          new StringSourceFile(path.relative(sourcePath), source);
       return source;
     });
   }
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 3ebafb1..141d83b 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
@@ -9,6 +9,7 @@
 import 'dart:isolate';
 
 import 'package:barback/barback.dart';
+import 'package:source_maps/source_maps.dart';
 
 import '../barback.dart';
 import '../dart.dart' as dart;
@@ -18,8 +19,8 @@
 
 /// A Dart script to run in an isolate.
 ///
-/// This script serializes one or more transformers defined in a Dart library and
-/// marhsals calls to and from them with the host isolate.
+/// This script serializes one or more transformers defined in a Dart library
+/// and marshals calls to and from them with the host isolate.
 const _TRANSFORMER_ISOLATE = """
 import 'dart:async';
 import 'dart:isolate';
@@ -90,16 +91,23 @@
 
   final Asset primaryInput;
 
-  // TODO(nweiz): implement this
-  TransformLogger get logger {
-    throw new UnimplementedError('ForeignTranform.logger is not yet '
-      'implemented.');
-  }
+  TransformLogger get logger => _logger;
+  TransformLogger _logger;
 
   /// Creates a transform from a serializable map sent from the host isolate.
   ForeignTransform(Map transform)
       : _port = transform['port'],
-        primaryInput = _deserializeAsset(transform['primaryInput']);
+        primaryInput = _deserializeAsset(transform['primaryInput']) {
+    _logger = new TransformLogger((assetId, level, message, span) {
+      _port.send({
+        'type': 'log',
+        'level': level.name,
+        'message': message,
+        'assetId': assetId == null ? null : _serializeId(assetId),
+        'span': span == null ? null : _serializeSpan(span)
+      });
+    });
+  }
 
   Future<Asset> getInput(AssetId id) {
     return _receiveFuture(_port.call({
@@ -108,6 +116,14 @@
     })).then(_deserializeAsset);
   }
 
+  Future<String> readInputAsString(AssetId id, {Encoding encoding}) {
+    if (encoding == null) encoding = UTF8;
+    return getInput(id).then((input) => input.readAsString(encoding: encoding));
+  }
+
+  Stream<List<int>> readInput(AssetId id) =>
+      _futureStream(getInput(id).then((input) => input.read()));
+
   void addOutput(Asset output) {
     _port.send({
       'type': 'addOutput',
@@ -223,6 +239,30 @@
 /// Converts [id] into a serializable map.
 Map _serializeId(AssetId id) => {'package': id.package, 'path': id.path};
 
+/// Converts [span] into a serializable map.
+Map _serializeSpan(Span span) {
+  // TODO(nweiz): convert FileSpans to FileSpans.
+  return {
+    'type': 'fixed',
+    'sourceUrl': span.sourceUrl,
+    'start': _serializeLocation(span.start),
+    'text': span.text,
+    'isIdentifier': span.isIdentifier
+  };
+}
+
+/// Converts [location] into a serializable map.
+Map _serializeLocation(Location location) {
+  // TODO(nweiz): convert FileLocations to FileLocations.
+  return {
+    'type': 'fixed',
+    'sourceUrl': location.sourceUrl,
+    'offset': location.offset,
+    'line': location.line,
+    'column': location.column
+  };
+}
+
 /// Sends the result of [future] through [port].
 ///
 /// This should be received on the other end using [_receiveFuture]. It
@@ -303,6 +343,23 @@
     return error.toString();
   }
 }
+
+/// Returns a buffered stream that will emit the same values as the stream
+/// returned by [future] once [future] completes. If [future] completes to an
+/// error, the return value will emit that error and then close.
+Stream _futureStream(Future<Stream> future) {
+  var controller = new StreamController(sync: true);
+  future.then((stream) {
+    stream.listen(
+        controller.add,
+        onError: controller.addError,
+        onDone: controller.close);
+  }).catchError((e, stackTrace) {
+    controller.addError(e, stackTrace);
+    controller.close();
+  });
+  return controller.stream;
+}
 """;
 
 /// Load and return all transformers and groups from the library identified by
@@ -405,9 +462,26 @@
     if (message['type'] == 'getInput') {
       _sendFuture(replyTo, transform.getInput(_deserializeId(message['id']))
           .then(_serializeAsset));
-    } else {
-      assert(message['type'] == 'addOutput');
+    } else if (message['type'] == 'addOutput') {
       transform.addOutput(_deserializeAsset(message['output']));
+    } else {
+      assert(message['type'] == 'log');
+
+      var method;
+      if (message['level'] == 'Info') {
+        method = transform.logger.info;
+      } else if (message['level'] == 'Warning') {
+        method = transform.logger.warning;
+      } else {
+        assert(message['level'] == 'Error');
+        method = transform.logger.error;
+      }
+
+      var assetId = message['assetId'] == null ? null :
+        _deserializeId(message['assetId']);
+      var span = message['span'] == null ? null :
+        _deserializeSpan(message['span']);
+      method(message['message'], asset: assetId, span: span);
     }
   });
 
@@ -427,6 +501,21 @@
 /// Converts a serializable map into an [AssetId].
 AssetId _deserializeId(Map id) => new AssetId(id['package'], id['path']);
 
+/// Converts a serializable map into a [Span].
+Span _deserializeSpan(Map span) {
+  assert(span['type'] == 'fixed');
+  var location = _deserializeLocation(span['start']);
+  return new FixedSpan(span['sourceUrl'], location.offset, location.line,
+      location.column, text: span['text'], isIdentifier: span['isIdentifier']);
+}
+
+/// Converts a serializable map into a [Location].
+Location _deserializeLocation(Map location) {
+  assert(location['type'] == 'fixed');
+  return new FixedLocation(location['offset'], location['sourceUrl'],
+      location['line'], location['column']);
+}
+
 // TODO(nweiz): add custom serialization code for assets that can be more
 // efficiently serialized.
 /// Converts [asset] into a serializable map.
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
index e9db32f..82686ca 100644
--- a/sdk/lib/_internal/pub/lib/src/dart.dart
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -13,7 +13,7 @@
 import 'package:stack_trace/stack_trace.dart';
 import '../../../compiler/compiler.dart' as compiler;
 import '../../../compiler/implementation/source_file_provider.dart'
-    show FormattingDiagnosticHandler, SourceFileProvider;
+    show FormattingDiagnosticHandler, CompilerSourceFileProvider;
 import '../../../compiler/implementation/filenames.dart'
     show appendSlash;
 
@@ -47,7 +47,7 @@
     }
 
     if (inputProvider == null) {
-      var provider = new SourceFileProvider();
+      var provider = new CompilerSourceFileProvider();
       inputProvider = provider.readStringFromUri;
       diagnosticHandler = new FormattingDiagnosticHandler(provider)
           .diagnosticHandler;
diff --git a/sdk/lib/_internal/pub/test/transformer/can_log_messages_test.dart b/sdk/lib/_internal/pub/test/transformer/can_log_messages_test.dart
new file mode 100644
index 0000000..c818a73
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/can_log_messages_test.dart
@@ -0,0 +1,70 @@
+// 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';
+
+const TRANSFORMER = """
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:source_maps/source_maps.dart';
+
+class RewriteTransformer extends Transformer {
+  RewriteTransformer.asPlugin();
+
+  String get allowedExtensions => '.txt';
+
+  Future apply(Transform transform) {
+    transform.logger.info('info!');
+    transform.logger.warning('Warning!',
+        asset: transform.primaryInput.id.changeExtension('.foo'));
+    var sourceFile = new SourceFile.text(
+        'http://fake.com/not_real.dart',
+        'not a real\\ndart file');
+    transform.logger.error('ERROR!', span: new FileSpan(sourceFile, 11));
+    return transform.primaryInput.readAsString().then((contents) {
+      var id = transform.primaryInput.id.changeExtension(".out");
+      transform.addOutput(new Asset.fromString(id, "\$contents.out"));
+    });
+  }
+}
+""";
+
+main() {
+  initConfig();
+  integration("can log messages", () {
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "transformers": ["myapp/src/transformer"]
+      }),
+      d.dir("lib", [d.dir("src", [
+        d.file("transformer.dart", TRANSFORMER)
+      ])]),
+      d.dir("web", [
+        d.file("foo.txt", "foo")
+      ])
+    ]).create();
+
+    createLockFile('myapp', pkg: ['barback']);
+
+    schedulePub(args: ["build"],
+        output: """
+Building myapp...
+[Rewrite on myapp|web/foo.txt]:
+info!
+""",
+        error: """
+[Rewrite on myapp|web/foo.txt with input myapp|web/foo.foo]:
+Warning!
+[Rewrite on myapp|web/foo.txt]:
+http://fake.com/not_real.dart:2:1: ERROR!
+Build failed.
+""",
+        exitCode: 65);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/transformer/can_use_read_input_as_string_test.dart b/sdk/lib/_internal/pub/test/transformer/can_use_read_input_as_string_test.dart
new file mode 100644
index 0000000..0084d5c
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/can_use_read_input_as_string_test.dart
@@ -0,0 +1,53 @@
+// 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';
+
+const TRANSFORMER = """
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+class RewriteTransformer extends Transformer {
+  RewriteTransformer.asPlugin();
+
+  String get allowedExtensions => '.txt';
+
+  Future apply(Transform transform) {
+    return transform.readInputAsString(transform.primaryInput.id)
+        .then((contents) {
+      var id = transform.primaryInput.id.changeExtension(".out");
+      transform.addOutput(new Asset.fromString(id, "\$contents.out"));
+    });
+  }
+}
+""";
+
+main() {
+  initConfig();
+  integration("a transform can use readInputAsString", () {
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "transformers": ["myapp/src/transformer"]
+      }),
+      d.dir("lib", [d.dir("src", [
+        d.file("transformer.dart", TRANSFORMER)
+      ])]),
+      d.dir("web", [
+        d.file("foo.txt", "foo")
+      ])
+    ]).create();
+
+    createLockFile('myapp', pkg: ['barback']);
+
+    startPubServe();
+    requestShouldSucceed("foo.out", "foo.out");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/transformer/can_use_read_input_test.dart b/sdk/lib/_internal/pub/test/transformer/can_use_read_input_test.dart
new file mode 100644
index 0000000..db700ca
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/can_use_read_input_test.dart
@@ -0,0 +1,54 @@
+// 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';
+
+const TRANSFORMER = """
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+class RewriteTransformer extends Transformer {
+  RewriteTransformer.asPlugin();
+
+  String get allowedExtensions => '.txt';
+
+  Future apply(Transform transform) {
+    return transform.readInput(transform.primaryInput.id).toList()
+        .then((contents) {
+      var id = transform.primaryInput.id.changeExtension(".out");
+      var asset = new Asset.fromString(id, "\$contents.out");
+      transform.addOutput(asset);
+    });
+  }
+}
+""";
+
+main() {
+  initConfig();
+  integration("a transform can use readInputAsString", () {
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "transformers": ["myapp/src/transformer"]
+      }),
+      d.dir("lib", [d.dir("src", [
+        d.file("transformer.dart", TRANSFORMER)
+      ])]),
+      d.dir("web", [
+        d.file("foo.txt", "foo")
+      ])
+    ]).create();
+
+    createLockFile('myapp', pkg: ['barback']);
+
+    startPubServe();
+    requestShouldSucceed("foo.out", "[[102, 111, 111]].out");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/convert/ascii.dart b/sdk/lib/convert/ascii.dart
index 56d6c89..8b98417 100644
--- a/sdk/lib/convert/ascii.dart
+++ b/sdk/lib/convert/ascii.dart
@@ -140,7 +140,7 @@
             "Source contains invalid character with code point: $codeUnit.");
       }
     }
-    _sink.add(source.codeUnits);
+    _sink.add(source.codeUnits.sublist(start, end));
     if (isLast) {
       close();
     }
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index b92d5cc..fb09d30 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -159,26 +159,32 @@
 
   /**
    * The keys of [this].
+   *
+   * The returned iterable has efficient `length` and `contains` operations,
+   * based on [length] and [containsKey] of the map.
    */
   Iterable<K> get keys;
 
   /**
    * The values of [this].
+   *
+   * The returned iterable has an efficient `length` method based on the
+   * [length] of the map.
    */
   Iterable<V> get values;
 
   /**
-   * The number of {key, value} pairs in the map.
+   * The number of key-value pairs in the map.
    */
   int get length;
 
   /**
-   * Returns true if there is no {key, value} pair in the map.
+   * Returns true if there is no key-value pair in the map.
    */
   bool get isEmpty;
 
   /**
-   * Returns true if there is at least one {key, value} pair in the map.
+   * Returns true if there is at least one key-value pair in the map.
    */
   bool get isNotEmpty;
 }
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index f8af64c..c22d0d7 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.dart
@@ -59,11 +59,11 @@
   bool contains(Object value);
 
   /**
-   * Adds [value] into the set.
+   * Adds [value] into the set. Returns `true` if [value] was added to the set.
    *
-   * The method has no effect if [value] is already in the set.
+   * If [value] already exists, the set is not changed and `false` is returned.
    */
-  void add(E value);
+  bool add(E value);
 
   /**
    * Adds all of [elements] to this Set.
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index fca06ef..ec9e4c4 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -6423,6 +6423,7 @@
   @DomName('CustomEvent._detail')
   @DocsEditable()
   @Experimental() // untriaged
+  @Creates('Null')
   final dynamic _get__detail;
 
   @JSName('initCustomEvent')
@@ -7118,7 +7119,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-@DocsEditable
+@DocsEditable()
 /**
  * The base class for all documents.
  *
@@ -9000,7 +9001,7 @@
 
 }
 
-@DocsEditable
+@DocsEditable()
 /**
  * An abstract class, which all HTML elements extend.
  */
@@ -9279,7 +9280,7 @@
   ElementList querySelectorAll(String selectors) =>
     new _FrozenElementList._wrap(_querySelectorAll(selectors));
 
-  /** 
+  /**
    * Alias for [querySelector]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -9288,7 +9289,7 @@
   @Experimental()
   Element query(String relativeSelectors) => querySelector(relativeSelectors);
 
-  /** 
+  /**
    * Alias for [querySelectorAll]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -10011,6 +10012,9 @@
     }
 
     treeSanitizer.sanitizeTree(fragment);
+    // Copy the fragment over to the main document (fix for 14184)
+    document.adoptNode(fragment);
+
     return fragment;
   }
 
@@ -10062,6 +10066,12 @@
     _innerHtml = html;
   }
 
+  /**
+   * This is an ease-of-use accessor for event streams which should only be
+   * used when an explicit accessor is not available.
+   */
+  ElementEvents get on => new ElementEvents(this);
+
   // To suppress missing implicit constructor warnings.
   factory Element._() { throw new UnsupportedError("Not supported"); }
 
@@ -11560,6 +11570,17 @@
   }
 }
 
+class ElementEvents extends Events {
+  /* Raw event target. */
+  final Element _ptr;
+
+  ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
+
+  Stream operator [](String type) {
+    return new _ElementEventStreamImpl(_ptr, type, false);
+  }
+}
+
 /**
  * Base class for all browser objects that support events.
  *
@@ -13351,8 +13372,8 @@
   /**
    * Makes a server POST request with the specified data encoded as form data.
    *
-   * This is roughly the POST equivalent of getString. This method is similar 
-   * to sending a FormData object with broader browser support but limited to 
+   * This is roughly the POST equivalent of getString. This method is similar
+   * to sending a FormData object with broader browser support but limited to
    * String values.
    *
    * See also:
@@ -13387,7 +13408,7 @@
    * Creates and sends a URL request for the specified [url].
    *
    * By default `request` will perform an HTTP GET request, but a different
-   * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the 
+   * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
    * [method] parameter.
    *
    * The Future is completed when the response is available.
@@ -13549,6 +13570,42 @@
     return completer.future;
   }
 
+  /**
+   * Returns all response headers as a key-value map.
+   *
+   * Multiple values for the same header key can be combined into one,
+   * separated by a comma and a space.
+   *
+   * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
+   */
+  Map<String, String> get responseHeaders {
+    // from Closure's goog.net.Xhrio.getResponseHeaders.
+    var headers = <String, String>{};
+    var headersString = this.getAllResponseHeaders();
+    if (headersString == null) {
+      return headers;
+    }
+    var headersList = headersString.split('\r\n');
+    for (var header in headersList) {
+      if (header.isEmpty) {
+        continue;
+      }
+
+      var splitIdx = header.indexOf(': ');
+      if (splitIdx == -1) {
+        continue;
+      }
+      var key = header.substring(0, splitIdx).toLowerCase();
+      var value = header.substring(splitIdx + 2);
+      if (headers.containsKey(key)) {
+        headers[key] = '${headers[key]}, $value';
+      } else {
+        headers[key] = value;
+      }
+    }
+    return headers;
+  }
+
   // To suppress missing implicit constructor warnings.
   factory HttpRequest._() { throw new UnsupportedError("Not supported"); }
 
@@ -18358,6 +18415,13 @@
   TemplateInstance get templateInstance =>
       TemplateElement.mdvPackage(this).templateInstance;
 
+
+  /**
+   * Use ownerDocument instead.
+   */
+  @deprecated
+  Document get document => ownerDocument;
+
   // To suppress missing implicit constructor warnings.
   factory Node._() { throw new UnsupportedError("Not supported"); }
 
@@ -18460,10 +18524,9 @@
   @DocsEditable()
   final String nodeValue;
 
-  @JSName('ownerDocument')
   @DomName('Node.ownerDocument')
   @DocsEditable()
-  final Document document;
+  final Document ownerDocument;
 
   @JSName('parentElement')
   @DomName('Node.parentElement')
@@ -19074,9 +19137,8 @@
 
 @DomName('HTMLOptionElement')
 class OptionElement extends HtmlElement native "HTMLOptionElement" {
-  factory OptionElement({String data, String value, bool defaultSelected, 
-      bool selected}) {
-    return new OptionElement._(data, value, defaultSelected, selected);
+  factory OptionElement({String data, String value, bool selected: false}) {
+    return new OptionElement._(data, value, false, selected);
   }
 
   @DomName('HTMLOptionElement.HTMLOptionElement')
@@ -23605,7 +23667,7 @@
     // Need to do this first as the contents may get lifted if |node| is
     // template.
     // TODO(jmesserly): content is DocumentFragment or Element
-    var descendents = 
+    var descendents =
         (content as dynamic).querySelectorAll(_allTemplatesSelectors);
     if (content is Element && (content as Element).isTemplate) {
       _bootstrap(content);
@@ -25494,7 +25556,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-@DocsEditable
+@DocsEditable()
 @DomName('Window')
 class Window extends EventTarget implements WindowBase, _WindowTimers, WindowBase64 native "Window,DOMWindow" {
 
@@ -28983,8 +29045,13 @@
    *
    * This is the Dart equivalent of jQuery's
    * [addClass](http://api.jquery.com/addClass/).
+   *
+   * If this corresponds to one element. Returns `true` if [value] was added to
+   * the set, otherwise `false`.
+   *
+   * If this corresponds to many elements, `null` is always returned.
    */
-  void add(String value);
+  bool add(String value);
 
   /**
    * Remove the class [value] from element, and return true on successful
@@ -29059,7 +29126,7 @@
    *   After f returns, the modified set is written to the
    *       className property of this element.
    */
-  void modify( f(Set<String> s)) {
+  modify( f(Set<String> s)) {
     _elementCssClassSetIterable.forEach((e) => e.modify(f));
   }
 
@@ -29497,6 +29564,8 @@
    * [delegate](http://api.jquery.com/delegate/).
    */
   Stream<T> matches(String selector);
+
+  StreamSubscription<T> capture(void onData(T event));
 }
 
 /**
@@ -29513,6 +29582,10 @@
         e._selector = selector;
         return e;
       });
+
+  StreamSubscription<T> capture(void onData(T event)) =>
+    new _EventStreamSubscription<T>(
+        this._target, this._eventType, onData, true);
 }
 
 /**
@@ -29521,17 +29594,12 @@
  */
 class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
     implements ElementStream<T> {
-  final _StreamPool _pool;
-  Stream<T> _stream;
+  final Iterable<Element> _targetList;
+  final bool _useCapture;
+  final String _eventType;
 
-  _ElementListEventStreamImpl(targetList, eventType, useCapture) :
-      _pool = new _StreamPool.broadcast() {
-    for (Element target in targetList) {
-      var stream = new _EventStream(target, eventType, useCapture);
-      _pool.add(stream);
-    }
-    _stream = _pool.stream;
-  }
+  _ElementListEventStreamImpl(
+      this._targetList, this._eventType, this._useCapture);
 
   Stream<T> matches(String selector) => this.where(
       (event) => event.target.matchesWithAncestors(selector)).map((e) {
@@ -29539,16 +29607,30 @@
         return e;
       });
 
-  // Delegate all regular Stream behavor to our wrapped Stream.
+  // Delegate all regular Stream behavior to a wrapped Stream.
   StreamSubscription<T> listen(void onData(T event),
       { Function onError,
         void onDone(),
-        bool cancelOnError}) =>
-      _stream.listen(onData, onError: onError, onDone: onDone,
+        bool cancelOnError}) {
+    var pool = new _StreamPool.broadcast();
+    for (var target in _targetList) {
+      pool.add(new _EventStream(target, _eventType, _useCapture));
+    }
+    return pool.stream.listen(onData, onError: onError, onDone: onDone,
           cancelOnError: cancelOnError);
+  }
+
+  StreamSubscription<T> capture(void onData(T event)) {
+    var pool = new _StreamPool.broadcast();
+    for (var target in _targetList) {
+      pool.add(new _EventStream(target, _eventType, true));
+    }
+    return pool.stream.listen(onData);
+  }
+
   Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
                                void onCancel(StreamSubscription subscription)})
-      => _stream;
+      => this;
   bool get isBroadcast => true;
 }
 
@@ -32772,30 +32854,6 @@
       convertDartClosureToJS(callback, 4));
 }
 
-const _typeNameToTag = const {
-  'HTMLAnchorElement': 'a',
-  'HTMLAudioElement': 'audio',
-  'HTMLButtonElement': 'button',
-  'HTMLCanvasElement': 'canvas',
-  'HTMLDivElement': 'div',
-  'HTMLImageElement': 'img',
-  'HTMLInputElement': 'input',
-  'HTMLLIElement': 'li',
-  'HTMLLabelElement': 'label',
-  'HTMLMenuElement': 'menu',
-  'HTMLMeterElement': 'meter',
-  'HTMLOListElement': 'ol',
-  'HTMLOptionElement': 'option',
-  'HTMLOutputElement': 'output',
-  'HTMLParagraphElement': 'p',
-  'HTMLPreElement': 'pre',
-  'HTMLProgressElement': 'progress',
-  'HTMLSelectElement': 'select',
-  'HTMLSpanElement': 'span',
-  'HTMLUListElement': 'ul',
-  'HTMLVideoElement': 'video',
-};
-
 void _registerCustomElement(context, document, String tag, Type type,
     String extendsTagName) {
   // Function follows the same pattern as the following JavaScript code for
@@ -32864,8 +32922,6 @@
   if (baseClassName != 'HTMLElement') {
     if (extendsTagName != null) {
       JS('=Object', '#.extends = #', options, extendsTagName);
-    } else if (_typeNameToTag.containsKey(baseClassName)) {
-      JS('=Object', '#.extends = #', options, _typeNameToTag[baseClassName]);
     }
   }
 
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 120c644..adc5b0e 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -118,7 +118,7 @@
 
 @DocsEditable()
 @DomName('AbstractWorker')
-class AbstractWorker extends NativeFieldWrapperClass1 implements EventTarget {
+class AbstractWorker extends NativeFieldWrapperClass2 implements EventTarget {
   // To suppress missing implicit constructor warnings.
   factory AbstractWorker._() { throw new UnsupportedError("Not supported"); }
 
@@ -180,7 +180,7 @@
 @DocsEditable()
 @DomName('Algorithm')
 @Experimental() // untriaged
-class Algorithm extends NativeFieldWrapperClass1 {
+class Algorithm extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Algorithm._() { throw new UnsupportedError("Not supported"); }
 
@@ -718,7 +718,7 @@
 @DomName('BarProp')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#barprop
 @deprecated // standard
-class BarProp extends NativeFieldWrapperClass1 {
+class BarProp extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory BarProp._() { throw new UnsupportedError("Not supported"); }
 
@@ -792,7 +792,7 @@
 
 
 @DomName('Blob')
-class Blob extends NativeFieldWrapperClass1 {
+class Blob extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Blob._() { throw new UnsupportedError("Not supported"); }
 
@@ -1114,7 +1114,7 @@
 @DomName('Canvas2DContextAttributes')
 // http://wiki.whatwg.org/wiki/CanvasOpaque#Suggested_IDL
 @Experimental()
-class Canvas2DContextAttributes extends NativeFieldWrapperClass1 {
+class Canvas2DContextAttributes extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Canvas2DContextAttributes._() { throw new UnsupportedError("Not supported"); }
 
@@ -1305,7 +1305,7 @@
  * * [CanvasGradient](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvasgradient) from W3C.
  */
 @DomName('CanvasGradient')
-class CanvasGradient extends NativeFieldWrapperClass1 {
+class CanvasGradient extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CanvasGradient._() { throw new UnsupportedError("Not supported"); }
 
@@ -1359,7 +1359,7 @@
  * * [CanvasPattern](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvaspattern) from W3C.
  */
 @DomName('CanvasPattern')
-class CanvasPattern extends NativeFieldWrapperClass1 {
+class CanvasPattern extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CanvasPattern._() { throw new UnsupportedError("Not supported"); }
 
@@ -1379,7 +1379,7 @@
  * [WebGLRenderingContext].
  */
 @DomName('CanvasRenderingContext')
-class CanvasRenderingContext extends NativeFieldWrapperClass1 {
+class CanvasRenderingContext extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CanvasRenderingContext._() { throw new UnsupportedError("Not supported"); }
 
@@ -2150,7 +2150,7 @@
 @DocsEditable()
 @DomName('ChildNode')
 @Experimental() // untriaged
-abstract class ChildNode extends NativeFieldWrapperClass1 {
+abstract class ChildNode extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ChildNode._() { throw new UnsupportedError("Not supported"); }
 
@@ -2230,7 +2230,7 @@
 @DomName('Composition')
 // http://www.w3.org/TR/ime-api/#idl-def-Composition
 @Experimental()
-class Composition extends NativeFieldWrapperClass1 {
+class Composition extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Composition._() { throw new UnsupportedError("Not supported"); }
 
@@ -2309,7 +2309,7 @@
 @DocsEditable()
 @DomName('ConsoleBase')
 @Experimental() // untriaged
-class ConsoleBase extends NativeFieldWrapperClass1 {
+class ConsoleBase extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ConsoleBase._() { throw new UnsupportedError("Not supported"); }
 
@@ -2478,7 +2478,7 @@
 
 @DocsEditable()
 @DomName('Coordinates')
-class Coordinates extends NativeFieldWrapperClass1 {
+class Coordinates extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Coordinates._() { throw new UnsupportedError("Not supported"); }
 
@@ -2524,7 +2524,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental()
 // http://www.w3.org/TR/WebCryptoAPI/
-class Crypto extends NativeFieldWrapperClass1 {
+class Crypto extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Crypto._() { throw new UnsupportedError("Not supported"); }
 
@@ -2551,7 +2551,7 @@
 @DocsEditable()
 @DomName('Key')
 @Experimental() // untriaged
-class CryptoKey extends NativeFieldWrapperClass1 {
+class CryptoKey extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CryptoKey._() { throw new UnsupportedError("Not supported"); }
 
@@ -2587,7 +2587,7 @@
 @DomName('CSS')
 // http://www.w3.org/TR/css3-conditional/#the-css-interface
 @Experimental() // None
-class Css extends NativeFieldWrapperClass1 {
+class Css extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Css._() { throw new UnsupportedError("Not supported"); }
 
@@ -2915,7 +2915,7 @@
 @Experimental()
 // http://dev.w3.org/csswg/cssom/
 @deprecated // deprecated
-class CssMatrix extends NativeFieldWrapperClass1 {
+class CssMatrix extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CssMatrix._() { throw new UnsupportedError("Not supported"); }
 
@@ -3251,7 +3251,7 @@
 
 @DocsEditable()
 @DomName('CSSRule')
-class CssRule extends NativeFieldWrapperClass1 {
+class CssRule extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CssRule._() { throw new UnsupportedError("Not supported"); }
 
@@ -3361,7 +3361,7 @@
 
 
 @DomName('CSSStyleDeclaration')
- class CssStyleDeclaration  extends NativeFieldWrapperClass1 with 
+ class CssStyleDeclaration  extends NativeFieldWrapperClass2 with 
     CssStyleDeclarationBase  {
   factory CssStyleDeclaration() => new CssStyleDeclaration.css('');
 
@@ -6874,7 +6874,7 @@
 @DocsEditable()
 @DomName('CSSVariablesMap')
 @Experimental() // untriaged
-class CssVariablesMap extends NativeFieldWrapperClass1 {
+class CssVariablesMap extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CssVariablesMap._() { throw new UnsupportedError("Not supported"); }
 
@@ -7049,7 +7049,7 @@
 
 @DocsEditable()
 @DomName('Clipboard')
-class DataTransfer extends NativeFieldWrapperClass1 {
+class DataTransfer extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DataTransfer._() { throw new UnsupportedError("Not supported"); }
 
@@ -7125,7 +7125,7 @@
 @DomName('DataTransferItem')
 // http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#the-datatransferitem-interface
 @Experimental()
-class DataTransferItem extends NativeFieldWrapperClass1 {
+class DataTransferItem extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DataTransferItem._() { throw new UnsupportedError("Not supported"); }
 
@@ -7171,7 +7171,7 @@
 @DomName('DataTransferItemList')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-datatransferitemlist-interface
 @Experimental()
-class DataTransferItemList extends NativeFieldWrapperClass1 {
+class DataTransferItemList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DataTransferItemList._() { throw new UnsupportedError("Not supported"); }
 
@@ -7306,7 +7306,7 @@
 @DomName('DeviceAcceleration')
 // http://dev.w3.org/geo/api/spec-source-orientation.html#devicemotion
 @Experimental()
-class DeviceAcceleration extends NativeFieldWrapperClass1 {
+class DeviceAcceleration extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DeviceAcceleration._() { throw new UnsupportedError("Not supported"); }
 
@@ -7408,7 +7408,7 @@
 @DomName('DeviceRotationRate')
 // http://dev.w3.org/geo/api/spec-source-orientation.html#devicemotion
 @Experimental()
-class DeviceRotationRate extends NativeFieldWrapperClass1 {
+class DeviceRotationRate extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DeviceRotationRate._() { throw new UnsupportedError("Not supported"); }
 
@@ -7578,7 +7578,7 @@
 @DomName('DirectoryReader')
 // http://www.w3.org/TR/file-system-api/#the-directoryreader-interface
 @Experimental()
-class DirectoryReader extends NativeFieldWrapperClass1 {
+class DirectoryReader extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DirectoryReader._() { throw new UnsupportedError("Not supported"); }
 
@@ -7646,7 +7646,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-@DocsEditable
+@DocsEditable()
 /**
  * The base class for all documents.
  *
@@ -8502,7 +8502,7 @@
 
 @DocsEditable()
 @DomName('DOMError')
-class DomError extends NativeFieldWrapperClass1 {
+class DomError extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DomError._() { throw new UnsupportedError("Not supported"); }
 
@@ -8523,7 +8523,7 @@
 
 @DomName('DOMException')
 @Unstable()
-class DomException extends NativeFieldWrapperClass1 {
+class DomException extends NativeFieldWrapperClass2 {
 
   static const String INDEX_SIZE = 'IndexSizeError';
   static const String HIERARCHY_REQUEST = 'HierarchyRequestError';
@@ -8572,7 +8572,7 @@
 
 @DocsEditable()
 @DomName('DOMImplementation')
-class DomImplementation extends NativeFieldWrapperClass1 {
+class DomImplementation extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DomImplementation._() { throw new UnsupportedError("Not supported"); }
 
@@ -8607,7 +8607,7 @@
 
 @DocsEditable()
 @DomName('DOMParser')
-class DomParser extends NativeFieldWrapperClass1 {
+class DomParser extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DomParser._() { throw new UnsupportedError("Not supported"); }
 
@@ -8660,7 +8660,7 @@
 
 @DocsEditable()
 @DomName('DOMStringList')
-class DomStringList extends NativeFieldWrapperClass1 with ListMixin<String>, ImmutableListMixin<String> implements List {
+class DomStringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List {
   // To suppress missing implicit constructor warnings.
   factory DomStringList._() { throw new UnsupportedError("Not supported"); }
 
@@ -8731,7 +8731,7 @@
 
 @DocsEditable()
 @DomName('DOMStringMap')
-abstract class DomStringMap extends NativeFieldWrapperClass1 {
+abstract class DomStringMap extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DomStringMap._() { throw new UnsupportedError("Not supported"); }
 
@@ -8757,7 +8757,7 @@
 
 @DocsEditable()
 @DomName('DOMTokenList')
-class DomTokenList extends NativeFieldWrapperClass1 {
+class DomTokenList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DomTokenList._() { throw new UnsupportedError("Not supported"); }
 
@@ -9553,7 +9553,7 @@
 
 }
 
-@DocsEditable
+@DocsEditable()
 /**
  * An abstract class, which all HTML elements extend.
  */
@@ -9832,7 +9832,7 @@
   ElementList querySelectorAll(String selectors) =>
     new _FrozenElementList._wrap(_querySelectorAll(selectors));
 
-  /** 
+  /**
    * Alias for [querySelector]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -9841,7 +9841,7 @@
   @Experimental()
   Element query(String relativeSelectors) => querySelector(relativeSelectors);
 
-  /** 
+  /**
    * Alias for [querySelectorAll]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -10400,6 +10400,9 @@
     }
 
     treeSanitizer.sanitizeTree(fragment);
+    // Copy the fragment over to the main document (fix for 14184)
+    document.adoptNode(fragment);
+
     return fragment;
   }
 
@@ -10451,6 +10454,12 @@
     _innerHtml = html;
   }
 
+  /**
+   * This is an ease-of-use accessor for event streams which should only be
+   * used when an explicit accessor is not available.
+   */
+  ElementEvents get on => new ElementEvents(this);
+
   // To suppress missing implicit constructor warnings.
   factory Element._() { throw new UnsupportedError("Not supported"); }
 
@@ -11409,7 +11418,7 @@
 @DomName('Entry')
 // http://www.w3.org/TR/file-system-api/#the-entry-interface
 @Experimental()
-class Entry extends NativeFieldWrapperClass1 {
+class Entry extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Entry._() { throw new UnsupportedError("Not supported"); }
 
@@ -11583,7 +11592,7 @@
 
 
 @DomName('Event')
-class Event extends NativeFieldWrapperClass1 {
+class Event extends NativeFieldWrapperClass2 {
   // In JS, canBubble and cancelable are technically required parameters to
   // init*Event. In practice, though, if they aren't provided they simply
   // default to false (since that's Boolean(undefined)).
@@ -11972,6 +11981,17 @@
   }
 }
 
+class ElementEvents extends Events {
+  /* Raw event target. */
+  final Element _ptr;
+
+  ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
+
+  Stream operator [](String type) {
+    return new _ElementEventStreamImpl(_ptr, type, false);
+  }
+}
+
 /**
  * Base class for all browser objects that support events.
  *
@@ -11980,7 +12000,7 @@
  * for compile-time type checks and a more concise API.
  */
 @DomName('EventTarget')
-class EventTarget extends NativeFieldWrapperClass1 {
+class EventTarget extends NativeFieldWrapperClass2 {
 
   // Custom element created callback.
   EventTarget._created();
@@ -12239,7 +12259,7 @@
 
 @DocsEditable()
 @DomName('FileList')
-class FileList extends NativeFieldWrapperClass1 with ListMixin<File>, ImmutableListMixin<File> implements List {
+class FileList extends NativeFieldWrapperClass2 with ListMixin<File>, ImmutableListMixin<File> implements List {
   // To suppress missing implicit constructor warnings.
   factory FileList._() { throw new UnsupportedError("Not supported"); }
 
@@ -12445,7 +12465,7 @@
 @DocsEditable()
 @DomName('Stream')
 @Experimental() // untriaged
-class FileStream extends NativeFieldWrapperClass1 {
+class FileStream extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory FileStream._() { throw new UnsupportedError("Not supported"); }
 
@@ -12467,7 +12487,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental()
 // http://www.w3.org/TR/file-system-api/
-class FileSystem extends NativeFieldWrapperClass1 {
+class FileSystem extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory FileSystem._() { throw new UnsupportedError("Not supported"); }
 
@@ -12747,7 +12767,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @SupportedBrowser(SupportedBrowser.SAFARI)
-class FormData extends NativeFieldWrapperClass1 {
+class FormData extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory FormData._() { throw new UnsupportedError("Not supported"); }
 
@@ -12931,7 +12951,7 @@
 @DomName('Gamepad')
 // https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepad-interface
 @Experimental()
-class Gamepad extends NativeFieldWrapperClass1 {
+class Gamepad extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Gamepad._() { throw new UnsupportedError("Not supported"); }
 
@@ -12964,7 +12984,7 @@
 @DocsEditable()
 @DomName('Geolocation')
 @Unstable()
-class Geolocation extends NativeFieldWrapperClass1 {
+class Geolocation extends NativeFieldWrapperClass2 {
 
   @DomName('Geolocation.getCurrentPosition')
   Future<Geoposition> getCurrentPosition({bool enableHighAccuracy,
@@ -13064,7 +13084,7 @@
 @DocsEditable()
 @DomName('Geoposition')
 @Unstable()
-class Geoposition extends NativeFieldWrapperClass1 {
+class Geoposition extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Geoposition._() { throw new UnsupportedError("Not supported"); }
 
@@ -13216,7 +13236,7 @@
 
 
 @DomName('History')
-class History extends NativeFieldWrapperClass1 implements HistoryBase {
+class History extends NativeFieldWrapperClass2 implements HistoryBase {
 
   /**
    * Checks if the State APIs are supported on the current platform.
@@ -13323,7 +13343,7 @@
 @DomName('HTMLAllCollection')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-document-all
 @deprecated // deprecated
-class HtmlAllCollection extends NativeFieldWrapperClass1 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class HtmlAllCollection extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
   // To suppress missing implicit constructor warnings.
   factory HtmlAllCollection._() { throw new UnsupportedError("Not supported"); }
 
@@ -13402,7 +13422,7 @@
 
 @DocsEditable()
 @DomName('HTMLCollection')
-class HtmlCollection extends NativeFieldWrapperClass1 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class HtmlCollection extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
   // To suppress missing implicit constructor warnings.
   factory HtmlCollection._() { throw new UnsupportedError("Not supported"); }
 
@@ -14007,8 +14027,8 @@
   /**
    * Makes a server POST request with the specified data encoded as form data.
    *
-   * This is roughly the POST equivalent of getString. This method is similar 
-   * to sending a FormData object with broader browser support but limited to 
+   * This is roughly the POST equivalent of getString. This method is similar
+   * to sending a FormData object with broader browser support but limited to
    * String values.
    *
    * See also:
@@ -14043,7 +14063,7 @@
    * Creates and sends a URL request for the specified [url].
    *
    * By default `request` will perform an HTTP GET request, but a different
-   * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the 
+   * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
    * [method] parameter.
    *
    * The Future is completed when the response is available.
@@ -14173,6 +14193,42 @@
     }
   }
 
+  /**
+   * Returns all response headers as a key-value map.
+   *
+   * Multiple values for the same header key can be combined into one,
+   * separated by a comma and a space.
+   *
+   * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
+   */
+  Map<String, String> get responseHeaders {
+    // from Closure's goog.net.Xhrio.getResponseHeaders.
+    var headers = <String, String>{};
+    var headersString = this.getAllResponseHeaders();
+    if (headersString == null) {
+      return headers;
+    }
+    var headersList = headersString.split('\r\n');
+    for (var header in headersList) {
+      if (header.isEmpty) {
+        continue;
+      }
+
+      var splitIdx = header.indexOf(': ');
+      if (splitIdx == -1) {
+        continue;
+      }
+      var key = header.substring(0, splitIdx).toLowerCase();
+      var value = header.substring(splitIdx + 2);
+      if (headers.containsKey(key)) {
+        headers[key] = '${headers[key]}, $value';
+      } else {
+        headers[key] = value;
+      }
+    }
+    return headers;
+  }
+
   // To suppress missing implicit constructor warnings.
   factory HttpRequest._() { throw new UnsupportedError("Not supported"); }
 
@@ -14585,7 +14641,7 @@
 @DocsEditable()
 @DomName('ImageBitmap')
 @Experimental() // untriaged
-class ImageBitmap extends NativeFieldWrapperClass1 {
+class ImageBitmap extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ImageBitmap._() { throw new UnsupportedError("Not supported"); }
 
@@ -14605,7 +14661,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @DomName('ImageData')
-class ImageData extends NativeFieldWrapperClass1 {
+class ImageData extends NativeFieldWrapperClass2 {
   List<int> __data;
 
   List<int> get data {
@@ -15865,7 +15921,7 @@
 @DomName('InputMethodContext')
 // http://www.w3.org/TR/ime-api/#idl-def-InputMethodContext
 @Experimental()
-class InputMethodContext extends NativeFieldWrapperClass1 {
+class InputMethodContext extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory InputMethodContext._() { throw new UnsupportedError("Not supported"); }
 
@@ -16304,7 +16360,7 @@
 
 @DocsEditable()
 @DomName('Location')
-class Location extends NativeFieldWrapperClass1 implements LocationBase {
+class Location extends NativeFieldWrapperClass2 implements LocationBase {
   // To suppress missing implicit constructor warnings.
   factory Location._() { throw new UnsupportedError("Not supported"); }
 
@@ -17166,7 +17222,7 @@
 @DocsEditable()
 @DomName('MediaError')
 @Unstable()
-class MediaError extends NativeFieldWrapperClass1 {
+class MediaError extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MediaError._() { throw new UnsupportedError("Not supported"); }
 
@@ -17208,7 +17264,7 @@
 @DomName('MediaKeyError')
 // https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1/encrypted-media/encrypted-media.html#error-codes
 @Experimental()
-class MediaKeyError extends NativeFieldWrapperClass1 {
+class MediaKeyError extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MediaKeyError._() { throw new UnsupportedError("Not supported"); }
 
@@ -17426,7 +17482,7 @@
 @DomName('MediaKeys')
 // https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1/encrypted-media/encrypted-media.html
 @Experimental()
-class MediaKeys extends NativeFieldWrapperClass1 {
+class MediaKeys extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MediaKeys._() { throw new UnsupportedError("Not supported"); }
 
@@ -17458,7 +17514,7 @@
 @DocsEditable()
 @DomName('MediaList')
 @Unstable()
-class MediaList extends NativeFieldWrapperClass1 {
+class MediaList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MediaList._() { throw new UnsupportedError("Not supported"); }
 
@@ -17497,7 +17553,7 @@
 @DocsEditable()
 @DomName('MediaQueryList')
 @Unstable()
-class MediaQueryList extends NativeFieldWrapperClass1 {
+class MediaQueryList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MediaQueryList._() { throw new UnsupportedError("Not supported"); }
 
@@ -17528,7 +17584,7 @@
 @DocsEditable()
 @DomName('MediaQueryListListener')
 @Unstable()
-abstract class MediaQueryListListener extends NativeFieldWrapperClass1 {
+abstract class MediaQueryListListener extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MediaQueryListListener._() { throw new UnsupportedError("Not supported"); }
 
@@ -17887,7 +17943,7 @@
 @DocsEditable()
 @DomName('MemoryInfo')
 @Experimental() // nonstandard
-class MemoryInfo extends NativeFieldWrapperClass1 {
+class MemoryInfo extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MemoryInfo._() { throw new UnsupportedError("Not supported"); }
 
@@ -17948,7 +18004,7 @@
 @DocsEditable()
 @DomName('MessageChannel')
 @Unstable()
-class MessageChannel extends NativeFieldWrapperClass1 {
+class MessageChannel extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MessageChannel._() { throw new UnsupportedError("Not supported"); }
 
@@ -18118,7 +18174,7 @@
 @DomName('Metadata')
 // http://www.w3.org/TR/file-system-api/#the-metadata-interface
 @Experimental()
-class Metadata extends NativeFieldWrapperClass1 {
+class Metadata extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Metadata._() { throw new UnsupportedError("Not supported"); }
 
@@ -18288,7 +18344,7 @@
 @DocsEditable()
 @DomName('MIDIAccessPromise')
 @Experimental() // untriaged
-class MidiAccessPromise extends NativeFieldWrapperClass1 {
+class MidiAccessPromise extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MidiAccessPromise._() { throw new UnsupportedError("Not supported"); }
 
@@ -18461,7 +18517,7 @@
 @DocsEditable()
 @DomName('MimeType')
 @Experimental() // non-standard
-class MimeType extends NativeFieldWrapperClass1 {
+class MimeType extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MimeType._() { throw new UnsupportedError("Not supported"); }
 
@@ -18492,7 +18548,7 @@
 @DocsEditable()
 @DomName('MimeTypeArray')
 @Experimental() // non-standard
-class MimeTypeArray extends NativeFieldWrapperClass1 with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements List {
+class MimeTypeArray extends NativeFieldWrapperClass2 with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements List {
   // To suppress missing implicit constructor warnings.
   factory MimeTypeArray._() { throw new UnsupportedError("Not supported"); }
 
@@ -18827,7 +18883,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental()
-class MutationObserver extends NativeFieldWrapperClass1 {
+class MutationObserver extends NativeFieldWrapperClass2 {
 
   @DomName('MutationObserver.MutationObserver')
   @DocsEditable()
@@ -18915,7 +18971,7 @@
 
 @DocsEditable()
 @DomName('MutationRecord')
-class MutationRecord extends NativeFieldWrapperClass1 {
+class MutationRecord extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory MutationRecord._() { throw new UnsupportedError("Not supported"); }
 
@@ -19023,7 +19079,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental()
 // http://dev.w3.org/csswg/css-regions/#dom-named-flow-collection
-class NamedFlowCollection extends NativeFieldWrapperClass1 {
+class NamedFlowCollection extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory NamedFlowCollection._() { throw new UnsupportedError("Not supported"); }
 
@@ -19050,7 +19106,7 @@
 
 
 @DomName('Navigator')
-class Navigator extends NativeFieldWrapperClass1 implements NavigatorOnLine, NavigatorID {
+class Navigator extends NativeFieldWrapperClass2 implements NavigatorOnLine, NavigatorID {
 
 
   /**
@@ -19249,7 +19305,7 @@
 @DocsEditable()
 @DomName('NavigatorID')
 @Experimental() // untriaged
-abstract class NavigatorID extends NativeFieldWrapperClass1 {
+abstract class NavigatorID extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory NavigatorID._() { throw new UnsupportedError("Not supported"); }
 
@@ -19284,7 +19340,7 @@
 @DocsEditable()
 @DomName('NavigatorOnLine')
 @Experimental() // untriaged
-abstract class NavigatorOnLine extends NativeFieldWrapperClass1 {
+abstract class NavigatorOnLine extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory NavigatorOnLine._() { throw new UnsupportedError("Not supported"); }
 
@@ -19305,7 +19361,7 @@
 @DomName('NavigatorUserMediaError')
 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-NavigatorUserMediaError
 @Experimental()
-class NavigatorUserMediaError extends NativeFieldWrapperClass1 {
+class NavigatorUserMediaError extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory NavigatorUserMediaError._() { throw new UnsupportedError("Not supported"); }
 
@@ -19652,6 +19708,13 @@
   TemplateInstance get templateInstance =>
       TemplateElement.mdvPackage(this).templateInstance;
 
+
+  /**
+   * Use ownerDocument instead.
+   */
+  @deprecated
+  Document get document => ownerDocument;
+
   // To suppress missing implicit constructor warnings.
   factory Node._() { throw new UnsupportedError("Not supported"); }
 
@@ -19750,7 +19813,7 @@
 
   @DomName('Node.ownerDocument')
   @DocsEditable()
-  Document get document native "Node_ownerDocument_Getter";
+  Document get ownerDocument native "Node_ownerDocument_Getter";
 
   @DomName('Node.parentElement')
   @DocsEditable()
@@ -19832,7 +19895,7 @@
 @DocsEditable()
 @DomName('NodeFilter')
 @Unstable()
-class NodeFilter extends NativeFieldWrapperClass1 {
+class NodeFilter extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory NodeFilter._() { throw new UnsupportedError("Not supported"); }
 
@@ -19913,7 +19976,7 @@
 
 @DomName('NodeIterator')
 @Unstable()
-class NodeIterator extends NativeFieldWrapperClass1 {
+class NodeIterator extends NativeFieldWrapperClass2 {
   factory NodeIterator(Node root, int whatToShow) {
     return document._createNodeIterator(root, whatToShow, null, false);
   }
@@ -19958,7 +20021,7 @@
 
 @DocsEditable()
 @DomName('NodeList')
-class NodeList extends NativeFieldWrapperClass1 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class NodeList extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
   // To suppress missing implicit constructor warnings.
   factory NodeList._() { throw new UnsupportedError("Not supported"); }
 
@@ -20202,7 +20265,7 @@
 @Experimental()
 // http://www.w3.org/TR/notifications/#showing-a-notification
 @deprecated // deprecated
-class NotificationCenter extends NativeFieldWrapperClass1 {
+class NotificationCenter extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory NotificationCenter._() { throw new UnsupportedError("Not supported"); }
 
@@ -20458,9 +20521,8 @@
 
 @DomName('HTMLOptionElement')
 class OptionElement extends HtmlElement {
-  factory OptionElement({String data, String value, bool defaultSelected, 
-      bool selected}) {
-    return new OptionElement._(data, value, defaultSelected, selected);
+  factory OptionElement({String data, String value, bool selected: false}) {
+    return new OptionElement._(data, value, false, selected);
   }
 
   @DomName('HTMLOptionElement.HTMLOptionElement')
@@ -20752,7 +20814,7 @@
 @DocsEditable()
 @DomName('ParentNode')
 @Experimental() // untriaged
-abstract class ParentNode extends NativeFieldWrapperClass1 {
+abstract class ParentNode extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ParentNode._() { throw new UnsupportedError("Not supported"); }
 
@@ -20788,7 +20850,7 @@
 @DomName('Path')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#path-objects
 @Experimental()
-class Path extends NativeFieldWrapperClass1 {
+class Path extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Path._() { throw new UnsupportedError("Not supported"); }
 
@@ -20984,7 +21046,7 @@
 @DomName('PerformanceEntry')
 // http://www.w3.org/TR/performance-timeline/#sec-PerformanceEntry-interface
 @Experimental()
-class PerformanceEntry extends NativeFieldWrapperClass1 {
+class PerformanceEntry extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PerformanceEntry._() { throw new UnsupportedError("Not supported"); }
 
@@ -21047,7 +21109,7 @@
 @DocsEditable()
 @DomName('PerformanceNavigation')
 @Unstable()
-class PerformanceNavigation extends NativeFieldWrapperClass1 {
+class PerformanceNavigation extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PerformanceNavigation._() { throw new UnsupportedError("Not supported"); }
 
@@ -21153,7 +21215,7 @@
 @DocsEditable()
 @DomName('PerformanceTiming')
 @Unstable()
-class PerformanceTiming extends NativeFieldWrapperClass1 {
+class PerformanceTiming extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PerformanceTiming._() { throw new UnsupportedError("Not supported"); }
 
@@ -21252,7 +21314,7 @@
 @DocsEditable()
 @DomName('Plugin')
 @Experimental() // non-standard
-class Plugin extends NativeFieldWrapperClass1 {
+class Plugin extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Plugin._() { throw new UnsupportedError("Not supported"); }
 
@@ -21295,7 +21357,7 @@
 @DocsEditable()
 @DomName('PluginArray')
 @Experimental() // non-standard
-class PluginArray extends NativeFieldWrapperClass1 with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements List {
+class PluginArray extends NativeFieldWrapperClass2 with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements List {
   // To suppress missing implicit constructor warnings.
   factory PluginArray._() { throw new UnsupportedError("Not supported"); }
 
@@ -21407,7 +21469,7 @@
 @DocsEditable()
 @DomName('PositionError')
 @Unstable()
-class PositionError extends NativeFieldWrapperClass1 {
+class PositionError extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PositionError._() { throw new UnsupportedError("Not supported"); }
 
@@ -21592,7 +21654,7 @@
 @DocsEditable()
 @DomName('Promise')
 @Experimental() // untriaged
-class Promise extends NativeFieldWrapperClass1 {
+class Promise extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Promise._() { throw new UnsupportedError("Not supported"); }
 
@@ -21637,7 +21699,7 @@
 @DocsEditable()
 @DomName('PromiseResolver')
 @Experimental() // untriaged
-class PromiseResolver extends NativeFieldWrapperClass1 {
+class PromiseResolver extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PromiseResolver._() { throw new UnsupportedError("Not supported"); }
 
@@ -21731,7 +21793,7 @@
 
 @DomName('Range')
 @Unstable()
-class Range extends NativeFieldWrapperClass1 {
+class Range extends NativeFieldWrapperClass2 {
   factory Range() => document.createRange();
 
   factory Range.fromPoint(Point point) =>
@@ -22275,7 +22337,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental()
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCIceCandidate
-class RtcIceCandidate extends NativeFieldWrapperClass1 {
+class RtcIceCandidate extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory RtcIceCandidate._() { throw new UnsupportedError("Not supported"); }
 
@@ -22548,7 +22610,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental()
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCSessionDescription
-class RtcSessionDescription extends NativeFieldWrapperClass1 {
+class RtcSessionDescription extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory RtcSessionDescription._() { throw new UnsupportedError("Not supported"); }
 
@@ -22589,7 +22651,7 @@
 @DomName('RTCStatsReport')
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCStatsReport
 @Experimental()
-class RtcStatsReport extends NativeFieldWrapperClass1 {
+class RtcStatsReport extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory RtcStatsReport._() { throw new UnsupportedError("Not supported"); }
 
@@ -22633,7 +22695,7 @@
 @DomName('RTCStatsResponse')
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#widl-RTCStatsReport-RTCStats-getter-DOMString-id
 @Experimental()
-class RtcStatsResponse extends NativeFieldWrapperClass1 {
+class RtcStatsResponse extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory RtcStatsResponse._() { throw new UnsupportedError("Not supported"); }
 
@@ -22657,7 +22719,7 @@
 
 @DocsEditable()
 @DomName('Screen')
-class Screen extends NativeFieldWrapperClass1 {
+class Screen extends NativeFieldWrapperClass2 {
 
   @DomName('Screen.availHeight')
   @DomName('Screen.availLeft')
@@ -22825,7 +22887,7 @@
 @DomName('SecurityPolicy')
 // https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#securitypolicy
 @Experimental()
-class SecurityPolicy extends NativeFieldWrapperClass1 {
+class SecurityPolicy extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SecurityPolicy._() { throw new UnsupportedError("Not supported"); }
 
@@ -23112,7 +23174,7 @@
 
 @DocsEditable()
 @DomName('Selection')
-class Selection extends NativeFieldWrapperClass1 {
+class Selection extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Selection._() { throw new UnsupportedError("Not supported"); }
 
@@ -23603,7 +23665,7 @@
 @DocsEditable()
 @DomName('SourceInfo')
 @Experimental() // untriaged
-class SourceInfo extends NativeFieldWrapperClass1 {
+class SourceInfo extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SourceInfo._() { throw new UnsupportedError("Not supported"); }
 
@@ -23663,7 +23725,7 @@
 @DomName('SpeechGrammar')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-speechgrammar
 @Experimental()
-class SpeechGrammar extends NativeFieldWrapperClass1 {
+class SpeechGrammar extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SpeechGrammar._() { throw new UnsupportedError("Not supported"); }
 
@@ -23704,7 +23766,7 @@
 @DomName('SpeechGrammarList')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-speechgrammarlist
 @Experimental()
-class SpeechGrammarList extends NativeFieldWrapperClass1 with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements List {
+class SpeechGrammarList extends NativeFieldWrapperClass2 with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements List {
   // To suppress missing implicit constructor warnings.
   factory SpeechGrammarList._() { throw new UnsupportedError("Not supported"); }
 
@@ -23828,7 +23890,7 @@
 @DomName('SpeechInputResult')
 // http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#speech_input_result_interface
 @Experimental()
-class SpeechInputResult extends NativeFieldWrapperClass1 {
+class SpeechInputResult extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SpeechInputResult._() { throw new UnsupportedError("Not supported"); }
 
@@ -24034,7 +24096,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME, '25')
 @Experimental()
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechrecognitionalternative
-class SpeechRecognitionAlternative extends NativeFieldWrapperClass1 {
+class SpeechRecognitionAlternative extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SpeechRecognitionAlternative._() { throw new UnsupportedError("Not supported"); }
 
@@ -24117,7 +24179,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME, '25')
 @Experimental()
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechrecognitionresult
-class SpeechRecognitionResult extends NativeFieldWrapperClass1 {
+class SpeechRecognitionResult extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SpeechRecognitionResult._() { throw new UnsupportedError("Not supported"); }
 
@@ -24145,7 +24207,7 @@
 @DomName('SpeechSynthesis')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#tts-section
 @Experimental()
-class SpeechSynthesis extends NativeFieldWrapperClass1 {
+class SpeechSynthesis extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SpeechSynthesis._() { throw new UnsupportedError("Not supported"); }
 
@@ -24365,7 +24427,7 @@
 @DomName('SpeechSynthesisVoice')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#tts-section
 @Experimental()
-class SpeechSynthesisVoice extends NativeFieldWrapperClass1 {
+class SpeechSynthesisVoice extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SpeechSynthesisVoice._() { throw new UnsupportedError("Not supported"); }
 
@@ -24422,7 +24484,7 @@
  */
 @DomName('Storage')
 @Unstable()
-class Storage extends NativeFieldWrapperClass1
+class Storage extends NativeFieldWrapperClass2
     implements Map<String, String>  {
 
   // TODO(nweiz): update this when maps support lazy iteration
@@ -24611,7 +24673,7 @@
 @DomName('StorageInfo')
 // http://www.w3.org/TR/file-system-api/
 @Experimental()
-class StorageInfo extends NativeFieldWrapperClass1 {
+class StorageInfo extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory StorageInfo._() { throw new UnsupportedError("Not supported"); }
 
@@ -24671,7 +24733,7 @@
 @DomName('StorageQuota')
 // http://www.w3.org/TR/quota-api/#idl-def-StorageQuota
 @Experimental()
-class StorageQuota extends NativeFieldWrapperClass1 {
+class StorageQuota extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory StorageQuota._() { throw new UnsupportedError("Not supported"); }
 
@@ -24796,7 +24858,7 @@
 @DomName('StyleMedia')
 // http://developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/StyleMedia/StyleMedia/StyleMedia.html
 @Experimental() // nonstandard
-class StyleMedia extends NativeFieldWrapperClass1 {
+class StyleMedia extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory StyleMedia._() { throw new UnsupportedError("Not supported"); }
 
@@ -24818,7 +24880,7 @@
 
 @DocsEditable()
 @DomName('StyleSheet')
-class StyleSheet extends NativeFieldWrapperClass1 {
+class StyleSheet extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory StyleSheet._() { throw new UnsupportedError("Not supported"); }
 
@@ -25456,7 +25518,7 @@
     // Need to do this first as the contents may get lifted if |node| is
     // template.
     // TODO(jmesserly): content is DocumentFragment or Element
-    var descendents = 
+    var descendents =
         (content as dynamic).querySelectorAll(_allTemplatesSelectors);
     if (content is Element && (content as Element).isTemplate) {
       _bootstrap(content);
@@ -25818,7 +25880,7 @@
 
 @DocsEditable()
 @DomName('TextMetrics')
-class TextMetrics extends NativeFieldWrapperClass1 {
+class TextMetrics extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory TextMetrics._() { throw new UnsupportedError("Not supported"); }
 
@@ -26074,7 +26136,7 @@
 @DomName('TextTrackCueList')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcuelist
 @Experimental()
-class TextTrackCueList extends NativeFieldWrapperClass1 with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List {
+class TextTrackCueList extends NativeFieldWrapperClass2 with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List {
   // To suppress missing implicit constructor warnings.
   factory TextTrackCueList._() { throw new UnsupportedError("Not supported"); }
 
@@ -26235,7 +26297,7 @@
 @DocsEditable()
 @DomName('TimeRanges')
 @Unstable()
-class TimeRanges extends NativeFieldWrapperClass1 {
+class TimeRanges extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory TimeRanges._() { throw new UnsupportedError("Not supported"); }
 
@@ -26294,7 +26356,7 @@
 @DomName('Touch')
 // http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
 @Experimental()
-class Touch extends NativeFieldWrapperClass1 {
+class Touch extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Touch._() { throw new UnsupportedError("Not supported"); }
 
@@ -26454,7 +26516,7 @@
 @DomName('TouchList')
 // http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
 @Experimental()
-class TouchList extends NativeFieldWrapperClass1 with ListMixin<Touch>, ImmutableListMixin<Touch> implements List {
+class TouchList extends NativeFieldWrapperClass2 with ListMixin<Touch>, ImmutableListMixin<Touch> implements List {
   /// 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.
@@ -26667,7 +26729,7 @@
 
 @DomName('TreeWalker')
 @Unstable()
-class TreeWalker extends NativeFieldWrapperClass1 {
+class TreeWalker extends NativeFieldWrapperClass2 {
   factory TreeWalker(Node root, int whatToShow) {
     return document._createTreeWalker(root, whatToShow, null, false);
   }
@@ -26880,7 +26942,7 @@
 
 @DocsEditable()
 @DomName('URL')
-class Url extends NativeFieldWrapperClass1 {
+class Url extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Url._() { throw new UnsupportedError("Not supported"); }
 
@@ -26893,13 +26955,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");
@@ -26939,7 +27001,7 @@
 
 @DocsEditable()
 @DomName('ValidityState')
-class ValidityState extends NativeFieldWrapperClass1 {
+class ValidityState extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ValidityState._() { throw new UnsupportedError("Not supported"); }
 
@@ -27456,7 +27518,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-@DocsEditable
+@DocsEditable()
 @DomName('Window')
 class Window extends EventTarget implements WindowBase, _WindowTimers, WindowBase64 {
 
@@ -28474,7 +28536,7 @@
 @DocsEditable()
 @DomName('WindowBase64')
 @Experimental() // untriaged
-abstract class WindowBase64 extends NativeFieldWrapperClass1 {
+abstract class WindowBase64 extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory WindowBase64._() { throw new UnsupportedError("Not supported"); }
 
@@ -28587,7 +28649,7 @@
 @DocsEditable()
 @DomName('WorkerCrypto')
 @Experimental() // untriaged
-class WorkerCrypto extends NativeFieldWrapperClass1 {
+class WorkerCrypto extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory WorkerCrypto._() { throw new UnsupportedError("Not supported"); }
 
@@ -28787,7 +28849,7 @@
 @DocsEditable()
 @DomName('WorkerPerformance')
 @Experimental() // untriaged
-class WorkerPerformance extends NativeFieldWrapperClass1 {
+class WorkerPerformance extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory WorkerPerformance._() { throw new UnsupportedError("Not supported"); }
 
@@ -28808,7 +28870,7 @@
 @DomName('XPathEvaluator')
 // http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator
 @deprecated // experimental
-class XPathEvaluator extends NativeFieldWrapperClass1 {
+class XPathEvaluator extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory XPathEvaluator._() { throw new UnsupportedError("Not supported"); }
 
@@ -28845,7 +28907,7 @@
 @DomName('XPathExpression')
 // http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathExpression
 @deprecated // experimental
-class XPathExpression extends NativeFieldWrapperClass1 {
+class XPathExpression extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory XPathExpression._() { throw new UnsupportedError("Not supported"); }
 
@@ -28865,7 +28927,7 @@
 @DomName('XPathNSResolver')
 // http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathNSResolver
 @deprecated // experimental
-class XPathNSResolver extends NativeFieldWrapperClass1 {
+class XPathNSResolver extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory XPathNSResolver._() { throw new UnsupportedError("Not supported"); }
 
@@ -28885,7 +28947,7 @@
 @DomName('XPathResult')
 // http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult
 @deprecated // experimental
-class XPathResult extends NativeFieldWrapperClass1 {
+class XPathResult extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory XPathResult._() { throw new UnsupportedError("Not supported"); }
 
@@ -29085,7 +29147,7 @@
 @DomName('XMLSerializer')
 // http://domparsing.spec.whatwg.org/#the-xmlserializer-interface
 @deprecated // stable
-class XmlSerializer extends NativeFieldWrapperClass1 {
+class XmlSerializer extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory XmlSerializer._() { throw new UnsupportedError("Not supported"); }
 
@@ -29116,7 +29178,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @deprecated // nonstandard
-class XsltProcessor extends NativeFieldWrapperClass1 {
+class XsltProcessor extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory XsltProcessor._() { throw new UnsupportedError("Not supported"); }
 
@@ -29242,7 +29304,7 @@
 @DomName('CSSValue')
 // http://dev.w3.org/csswg/cssom/
 @deprecated // deprecated
-abstract class _CSSValue extends NativeFieldWrapperClass1 {
+abstract class _CSSValue extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _CSSValue._() { throw new UnsupportedError("Not supported"); }
 
@@ -29254,7 +29316,7 @@
 
 @DocsEditable()
 @DomName('ClientRect')
-class _ClientRect extends NativeFieldWrapperClass1 implements Rectangle {
+class _ClientRect extends NativeFieldWrapperClass2 implements Rectangle {
 
   // NOTE! All code below should be common with RectangleBase.
    String toString() {
@@ -29418,7 +29480,7 @@
 
 @DocsEditable()
 @DomName('ClientRectList')
-class _ClientRectList extends NativeFieldWrapperClass1 with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List {
+class _ClientRectList extends NativeFieldWrapperClass2 with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List {
   // To suppress missing implicit constructor warnings.
   factory _ClientRectList._() { throw new UnsupportedError("Not supported"); }
 
@@ -29487,7 +29549,7 @@
 @DomName('Counter')
 // http://dev.w3.org/csswg/cssom/
 @deprecated // deprecated
-abstract class _Counter extends NativeFieldWrapperClass1 {
+abstract class _Counter extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _Counter._() { throw new UnsupportedError("Not supported"); }
 
@@ -29501,7 +29563,7 @@
 
 @DocsEditable()
 @DomName('CSSRuleList')
-class _CssRuleList extends NativeFieldWrapperClass1 with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements List {
+class _CssRuleList extends NativeFieldWrapperClass2 with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements List {
   // To suppress missing implicit constructor warnings.
   factory _CssRuleList._() { throw new UnsupportedError("Not supported"); }
 
@@ -29640,7 +29702,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental()
 // http://www.w3.org/TR/file-system-api/#the-filesystemsync-interface
-abstract class _DOMFileSystemSync extends NativeFieldWrapperClass1 {
+abstract class _DOMFileSystemSync extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _DOMFileSystemSync._() { throw new UnsupportedError("Not supported"); }
 
@@ -29659,7 +29721,7 @@
 @Experimental()
 // http://www.w3.org/TR/webdatabase/#databasesync
 @deprecated // deprecated
-abstract class _DatabaseSync extends NativeFieldWrapperClass1 {
+abstract class _DatabaseSync extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _DatabaseSync._() { throw new UnsupportedError("Not supported"); }
 
@@ -29691,7 +29753,7 @@
 @DomName('DirectoryReaderSync')
 // http://www.w3.org/TR/file-system-api/#idl-def-DirectoryReaderSync
 @Experimental()
-abstract class _DirectoryReaderSync extends NativeFieldWrapperClass1 {
+abstract class _DirectoryReaderSync extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _DirectoryReaderSync._() { throw new UnsupportedError("Not supported"); }
 
@@ -29710,7 +29772,7 @@
 @Experimental()
 // http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html
 @Experimental() // non-standard
-class _DomPoint extends NativeFieldWrapperClass1 {
+class _DomPoint extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _DomPoint._() { throw new UnsupportedError("Not supported"); }
 
@@ -29779,7 +29841,7 @@
 @DomName('EntrySync')
 // http://www.w3.org/TR/file-system-api/#idl-def-EntrySync
 @Experimental()
-abstract class _EntrySync extends NativeFieldWrapperClass1 {
+abstract class _EntrySync extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _EntrySync._() { throw new UnsupportedError("Not supported"); }
 
@@ -29811,7 +29873,7 @@
 @DomName('FileReaderSync')
 // http://www.w3.org/TR/FileAPI/#FileReaderSync
 @Experimental()
-abstract class _FileReaderSync extends NativeFieldWrapperClass1 {
+abstract class _FileReaderSync extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _FileReaderSync._() { throw new UnsupportedError("Not supported"); }
 
@@ -29836,7 +29898,7 @@
 @DomName('FileWriterSync')
 // http://www.w3.org/TR/file-writer-api/#idl-def-FileWriterSync
 @Experimental()
-abstract class _FileWriterSync extends NativeFieldWrapperClass1 {
+abstract class _FileWriterSync extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _FileWriterSync._() { throw new UnsupportedError("Not supported"); }
 
@@ -29852,7 +29914,7 @@
 @DomName('GamepadList')
 // https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html
 @Experimental()
-class _GamepadList extends NativeFieldWrapperClass1 with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements List {
+class _GamepadList extends NativeFieldWrapperClass2 with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements List {
   // To suppress missing implicit constructor warnings.
   factory _GamepadList._() { throw new UnsupportedError("Not supported"); }
 
@@ -30075,7 +30137,7 @@
 @DomName('NamedNodeMap')
 // http://dom.spec.whatwg.org/#namednodemap
 @deprecated // deprecated
-class _NamedNodeMap extends NativeFieldWrapperClass1 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class _NamedNodeMap extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
   // To suppress missing implicit constructor warnings.
   factory _NamedNodeMap._() { throw new UnsupportedError("Not supported"); }
 
@@ -30171,7 +30233,7 @@
 @DocsEditable()
 @DomName('PagePopupController')
 @deprecated // nonstandard
-abstract class _PagePopupController extends NativeFieldWrapperClass1 {
+abstract class _PagePopupController extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _PagePopupController._() { throw new UnsupportedError("Not supported"); }
 
@@ -30187,7 +30249,7 @@
 @DomName('RGBColor')
 // http://dev.w3.org/csswg/cssom/
 @deprecated // deprecated
-abstract class _RGBColor extends NativeFieldWrapperClass1 {
+abstract class _RGBColor extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _RGBColor._() { throw new UnsupportedError("Not supported"); }
 
@@ -30214,7 +30276,7 @@
 @DomName('Rect')
 // http://dev.w3.org/csswg/cssom/
 @deprecated // deprecated
-abstract class _Rect extends NativeFieldWrapperClass1 {
+abstract class _Rect extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _Rect._() { throw new UnsupportedError("Not supported"); }
 
@@ -30255,7 +30317,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 NativeFieldWrapperClass1 with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements List {
+class _SpeechInputResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements List {
   // To suppress missing implicit constructor warnings.
   factory _SpeechInputResultList._() { throw new UnsupportedError("Not supported"); }
 
@@ -30324,7 +30386,7 @@
 @DomName('SpeechRecognitionResultList')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechrecognitionresultlist
 @Experimental()
-class _SpeechRecognitionResultList extends NativeFieldWrapperClass1 with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements List {
+class _SpeechRecognitionResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements List {
   // To suppress missing implicit constructor warnings.
   factory _SpeechRecognitionResultList._() { throw new UnsupportedError("Not supported"); }
 
@@ -30391,7 +30453,7 @@
 
 @DocsEditable()
 @DomName('StyleSheetList')
-class _StyleSheetList extends NativeFieldWrapperClass1 with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements List {
+class _StyleSheetList extends NativeFieldWrapperClass2 with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements List {
   // To suppress missing implicit constructor warnings.
   factory _StyleSheetList._() { throw new UnsupportedError("Not supported"); }
 
@@ -30463,7 +30525,7 @@
 @DocsEditable()
 @DomName('SubtleCrypto')
 @Experimental() // untriaged
-abstract class _SubtleCrypto extends NativeFieldWrapperClass1 {
+abstract class _SubtleCrypto extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _SubtleCrypto._() { throw new UnsupportedError("Not supported"); }
 
@@ -30502,7 +30564,7 @@
 @DocsEditable()
 @DomName('WebKitSourceBuffer')
 @Experimental() // untriaged
-abstract class _WebKitSourceBuffer extends NativeFieldWrapperClass1 {
+abstract class _WebKitSourceBuffer extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _WebKitSourceBuffer._() { throw new UnsupportedError("Not supported"); }
 
@@ -30537,7 +30599,7 @@
 @DocsEditable()
 @DomName('WindowTimers')
 @Experimental() // untriaged
-abstract class _WindowTimers extends NativeFieldWrapperClass1 {
+abstract class _WindowTimers extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _WindowTimers._() { throw new UnsupportedError("Not supported"); }
 
@@ -30573,7 +30635,7 @@
 @DomName('WorkerLocation')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workerlocation
 @Experimental()
-abstract class _WorkerLocation extends NativeFieldWrapperClass1 {
+abstract class _WorkerLocation extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _WorkerLocation._() { throw new UnsupportedError("Not supported"); }
 
@@ -30589,7 +30651,7 @@
 @DomName('WorkerNavigator')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workernavigator
 @Experimental()
-abstract class _WorkerNavigator extends NativeFieldWrapperClass1 implements NavigatorOnLine, NavigatorID {
+abstract class _WorkerNavigator extends NativeFieldWrapperClass2 implements NavigatorOnLine, NavigatorID {
   // To suppress missing implicit constructor warnings.
   factory _WorkerNavigator._() { throw new UnsupportedError("Not supported"); }
 
@@ -31065,8 +31127,13 @@
    *
    * This is the Dart equivalent of jQuery's
    * [addClass](http://api.jquery.com/addClass/).
+   *
+   * If this corresponds to one element. Returns `true` if [value] was added to
+   * the set, otherwise `false`.
+   *
+   * If this corresponds to many elements, `null` is always returned.
    */
-  void add(String value);
+  bool add(String value);
 
   /**
    * Remove the class [value] from element, and return true on successful
@@ -31141,7 +31208,7 @@
    *   After f returns, the modified set is written to the
    *       className property of this element.
    */
-  void modify( f(Set<String> s)) {
+  modify( f(Set<String> s)) {
     _elementCssClassSetIterable.forEach((e) => e.modify(f));
   }
 
@@ -31579,6 +31646,8 @@
    * [delegate](http://api.jquery.com/delegate/).
    */
   Stream<T> matches(String selector);
+
+  StreamSubscription<T> capture(void onData(T event));
 }
 
 /**
@@ -31595,6 +31664,10 @@
         e._selector = selector;
         return e;
       });
+
+  StreamSubscription<T> capture(void onData(T event)) =>
+    new _EventStreamSubscription<T>(
+        this._target, this._eventType, onData, true);
 }
 
 /**
@@ -31603,17 +31676,12 @@
  */
 class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
     implements ElementStream<T> {
-  final _StreamPool _pool;
-  Stream<T> _stream;
+  final Iterable<Element> _targetList;
+  final bool _useCapture;
+  final String _eventType;
 
-  _ElementListEventStreamImpl(targetList, eventType, useCapture) :
-      _pool = new _StreamPool.broadcast() {
-    for (Element target in targetList) {
-      var stream = new _EventStream(target, eventType, useCapture);
-      _pool.add(stream);
-    }
-    _stream = _pool.stream;
-  }
+  _ElementListEventStreamImpl(
+      this._targetList, this._eventType, this._useCapture);
 
   Stream<T> matches(String selector) => this.where(
       (event) => event.target.matchesWithAncestors(selector)).map((e) {
@@ -31621,16 +31689,30 @@
         return e;
       });
 
-  // Delegate all regular Stream behavor to our wrapped Stream.
+  // Delegate all regular Stream behavior to a wrapped Stream.
   StreamSubscription<T> listen(void onData(T event),
       { Function onError,
         void onDone(),
-        bool cancelOnError}) =>
-      _stream.listen(onData, onError: onError, onDone: onDone,
+        bool cancelOnError}) {
+    var pool = new _StreamPool.broadcast();
+    for (var target in _targetList) {
+      pool.add(new _EventStream(target, _eventType, _useCapture));
+    }
+    return pool.stream.listen(onData, onError: onError, onDone: onDone,
           cancelOnError: cancelOnError);
+  }
+
+  StreamSubscription<T> capture(void onData(T event)) {
+    var pool = new _StreamPool.broadcast();
+    for (var target in _targetList) {
+      pool.add(new _EventStream(target, _eventType, true));
+    }
+    return pool.stream.listen(onData);
+  }
+
   Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
                                void onCancel(StreamSubscription subscription)})
-      => _stream;
+      => this;
   bool get isBroadcast => true;
 }
 
@@ -35271,9 +35353,12 @@
     return false;
   }
 
-  static bool isTypeSubclassOfTag(Type type, String tagName) {
+  static Element getAndValidateNativeType(Type type, String tagName) {
     var element = new Element.tag(tagName);
-    return isTypeSubclassOf(type, element.runtimeType);
+    if (!isTypeSubclassOf(type, element.runtimeType)) {
+      return null;
+    }
+    return element;
   }
 
   static window() native "Utils_window";
@@ -35590,7 +35675,7 @@
   static void initializeCustomElement(HtmlElement element) native "Utils_initializeCustomElement";
 }
 
-class _DOMWindowCrossFrame extends NativeFieldWrapperClass1 implements
+class _DOMWindowCrossFrame extends NativeFieldWrapperClass2 implements
     WindowBase {
   _DOMWindowCrossFrame.internal();
 
@@ -35611,7 +35696,7 @@
   String get typeName => "Window";
 }
 
-class _HistoryCrossFrame extends NativeFieldWrapperClass1 implements HistoryBase {
+class _HistoryCrossFrame extends NativeFieldWrapperClass2 implements HistoryBase {
   _HistoryCrossFrame.internal();
 
   // Methods.
@@ -35623,7 +35708,7 @@
   String get typeName => "History";
 }
 
-class _LocationCrossFrame extends NativeFieldWrapperClass1 implements LocationBase {
+class _LocationCrossFrame extends NativeFieldWrapperClass2 implements LocationBase {
   _LocationCrossFrame.internal();
 
   // Fields.
@@ -35633,7 +35718,7 @@
   String get typeName => "Location";
 }
 
-class _DOMStringMap extends NativeFieldWrapperClass1 implements Map<String, String> {
+class _DOMStringMap extends NativeFieldWrapperClass2 implements Map<String, String> {
   _DOMStringMap.internal();
 
   bool containsValue(String value) => Maps.containsValue(this, value);
@@ -35704,10 +35789,14 @@
   Function _callback;
 
   _ScheduleImmediateHelper() {
-    // Mutation events get fired as soon as the current event stack is unwound
-    // so we just make a dummy event and listen for that.
-    _observer = new MutationObserver(_handleMutation);
-    _observer.observe(_div, attributes: true);
+    // Run in the root-zone as the DOM callback would otherwise execute in the
+    // current zone.
+    Zone.ROOT.run(() {
+      // Mutation events get fired as soon as the current event stack is unwound
+      // so we just make a dummy event and listen for that.
+      _observer = new MutationObserver(_handleMutation);
+      _observer.observe(_div, attributes: true);
+    });
   }
 
   void _schedule(callback) {
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index 1e2dce7..a81497e 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.dart
@@ -92,10 +92,10 @@
    * This is the Dart equivalent of jQuery's
    * [addClass](http://api.jquery.com/addClass/).
    */
-  void add(String value) {
+  bool add(String value) {
     // TODO - figure out if we need to do any validation here
     // or if the browser natively does enough.
-    modify((s) => s.add(value));
+    return modify((s) => s.add(value));
   }
 
   /**
@@ -206,10 +206,11 @@
    *   After f returns, the modified set is written to the
    *       className property of this element.
    */
-  void modify( f(Set<String> s)) {
+  modify( f(Set<String> s)) {
     Set<String> s = readClasses();
-    f(s);
+    var ret = f(s);
     writeClasses(s);
+    return ret;
   }
 
   /**
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 5b2948d..e5d187f 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -1261,7 +1261,10 @@
     });
 
     this.onAbort.first.then((e) {
-      completer.completeError(e);
+      // Avoid completing twice if an error occurs.
+      if (!completer.isCompleted) {
+        completer.completeError(e);
+      }
     });
 
     return completer.future;
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 34dcf6b..3a467ba 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -40,7 +40,7 @@
 
 @DomName('IDBCursor')
 @Unstable()
-class Cursor extends NativeFieldWrapperClass1 {
+class Cursor extends NativeFieldWrapperClass2 {
   @DomName('IDBCursor.delete')
   Future delete() {
    try {
@@ -265,7 +265,7 @@
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @Experimental()
 @Unstable()
-class IdbFactory extends NativeFieldWrapperClass1 {
+class IdbFactory extends NativeFieldWrapperClass2 {
   /**
    * Checks to see if Indexed DB is supported on the current platform.
    */
@@ -394,7 +394,7 @@
 
 @DomName('IDBIndex')
 @Unstable()
-class Index extends NativeFieldWrapperClass1 {
+class Index extends NativeFieldWrapperClass2 {
   @DomName('IDBIndex.count')
   Future<int> count([key_OR_range]) {
    try {
@@ -532,7 +532,7 @@
 
 @DomName('IDBKeyRange')
 @Unstable()
-class KeyRange extends NativeFieldWrapperClass1 {
+class KeyRange extends NativeFieldWrapperClass2 {
   @DomName('IDBKeyRange.only')
   factory KeyRange.only(/*Key*/ value) =>
       _KeyRangeFactoryProvider.createKeyRange_only(value);
@@ -598,7 +598,7 @@
 
 @DomName('IDBObjectStore')
 @Unstable()
-class ObjectStore extends NativeFieldWrapperClass1 {
+class ObjectStore extends NativeFieldWrapperClass2 {
 
   @DomName('IDBObjectStore.add')
   Future add(value, [key]) {
@@ -949,7 +949,10 @@
     });
 
     this.onAbort.first.then((e) {
-      completer.completeError(e);
+      // Avoid completing twice if an error occurs.
+      if (!completer.isCompleted) {
+        completer.completeError(e);
+      }
     });
 
     return completer.future;
@@ -1053,7 +1056,7 @@
 @DocsEditable()
 @DomName('IDBAny')
 @deprecated // nonstandard
-abstract class _IDBAny extends NativeFieldWrapperClass1 {
+abstract class _IDBAny extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _IDBAny._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 35968a9..213a444 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -4,50 +4,17 @@
 
 library dart.js;
 
+import 'dart:html' show Blob, ImageData, Node;
+import 'dart:collection' show HashMap;
+import 'dart:indexed_db' show KeyRange;
+import 'dart:typed_data' show TypedData;
+
 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
+import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject;
 import 'dart:_js_helper' show Primitives, convertDartClosureToJS;
 
 final JsObject context = new JsObject._fromJs(Primitives.computeGlobalThis());
 
-JsObject jsify(dynamic data) => data == null ? null : new JsObject._json(data);
-
-class Callback implements Serializable<JsFunction> {
-  final Function _f; // here to allow capture in closure
-  final bool _withThis; // here to allow capture in closure
-  dynamic _jsFunction;
-
-  Callback._(this._f, this._withThis) {
-    _jsFunction = JS('=Object', r'''
-(function(){
-  var f = #;
-  return function(){
-    return f(this, Array.prototype.slice.apply(arguments));
-  };
-}).apply(this)''', convertDartClosureToJS(_call, 2));
-  }
-
-  factory Callback(Function f) => new Callback._(f, false);
-  factory Callback.withThis(Function f) => new Callback._(f, true);
-
-  _call(thisArg, List args) {
-    final arguments = new List.from(args);
-    if (_withThis) arguments.insert(0, thisArg);
-    final dartArgs = arguments.map(_convertToDart).toList();
-    return _convertToJS(Function.apply(_f, dartArgs));
-  }
-
-  JsFunction toJs() => new JsFunction._fromJs(_jsFunction);
-}
-
-/*
- * TODO(justinfagnani): add tests and make public when we remove Callback.
- *
- * Returns a [JsFunction] that captures its 'this' binding and calls [f]
- * with the value of this passed as the first argument.
- */
-JsFunction _captureThis(Function f) => 
-  new JsFunction._fromJs(_convertDartFunction(f, captureThis: true));
-
 _convertDartFunction(Function f, {bool captureThis: false}) {
   return JS('',
     'function(_call, f, captureThis) {'
@@ -67,137 +34,182 @@
 }
 
 
-class JsObject implements Serializable<JsObject> {
+class JsObject {
+  // The wrapped JS object.
   final dynamic _jsObject;
 
   JsObject._fromJs(this._jsObject) {
-    // remember this proxy for the JS object
+    assert(_jsObject != null);
+    // Remember this proxy for the JS object
     _getDartProxy(_jsObject, _DART_OBJECT_PROPERTY_NAME, (o) => this);
   }
 
-  // TODO(vsm): Type constructor as Serializable<JsFunction> when
-  // dartbug.com/11854 is fixed.
-  factory JsObject(var constructor, [List arguments]) {
-    final constr = _convertToJS(constructor);
+  /**
+   * Expert use only:
+   *
+   * Use this constructor only if you wish to get access to JS properties
+   * attached to a browser host object such as a Node or Blob. This constructor
+   * will return a JsObject proxy on [object], even though the object would
+   * normally be returned as a native Dart object.
+   * 
+   * An exception will be thrown if [object] is a primitive type or null.
+   */
+  factory JsObject.fromBrowserObject(Object object) {
+    if (object is num || object is String || object is bool || object == null) {
+      throw new ArgumentError(
+        "object cannot be a num, string, bool, or null");
+    }
+    return new JsObject._fromJs(_convertToJS(object));
+  }
+
+  /**
+   * Converts a json-like [data] to a JavaScript map or array and return a
+   * [JsObject] to it.
+   */
+  factory JsObject.jsify(Object object) {
+    if ((object is! Map) && (object is! Iterable)) {
+      throw new ArgumentError("object must be a Map or Iterable");
+    }
+    return new JsObject._fromJs(_convertDataTree(object));
+  }
+
+  factory JsObject(JsFunction constructor, [List arguments]) {
+    var constr = _convertToJS(constructor);
     if (arguments == null) {
-      return new JsObject._fromJs(JS('=Object', 'new #()', constr));
+      return new JsObject._fromJs(JS('', 'new #()', constr));
     }
-    final args = arguments.map(_convertToJS).toList();
-    switch (args.length) {
-      case 0:
-        return new JsObject._fromJs(JS('=Object', 'new #()', constr));
-      case 1:
-        return new JsObject._fromJs(JS('=Object', 'new #(#)', constr, args[0]));
-      case 2:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#)', constr, args[0],
-            args[1]));
-      case 3:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#)', constr,
-            args[0], args[1], args[2]));
-      case 4:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#)', constr,
-            args[0], args[1], args[2], args[3]));
-      case 5:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#)', constr,
-            args[0], args[1], args[2], args[3], args[4]));
-      case 6:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#)', constr,
-            args[0], args[1], args[2], args[3], args[4], args[5]));
-      case 7:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#)',
-            constr, args[0], args[1], args[2], args[3], args[4], args[5],
-            args[6]));
-      case 8:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#)',
-            constr, args[0], args[1], args[2], args[3], args[4], args[5],
-            args[6], args[7]));
-      case 9:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#,#)',
-            constr, args[0], args[1], args[2], args[3], args[4], args[5],
-            args[6], args[7], args[8]));
-      case 10:
-        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#,#,#)',
-            constr, args[0], args[1], args[2], args[3], args[4], args[5],
-            args[6], args[7], args[8], args[9]));
-    }
-    return new JsObject._fromJs(JS('=Object', r'''(function(){
-var Type = function(){};
-Type.prototype = #.prototype;
-var instance = new Type();
-ret = #.apply(instance, #);
-ret = Object(ret) === ret ? ret : instance;
-return ret;
-})()''', constr, constr, args));
+    // The following code solves the problem of invoking a JavaScript
+    // constructor with an unknown number arguments.
+    // First bind the constructor to the argument list using bind.apply().
+    // The first argument to bind() is the binding of 'this', so add 'null' to
+    // the arguments list passed to apply().
+    // After that, use the JavaScript 'new' operator which overrides any binding
+    // of 'this' with the new instance.
+    var args = [null]..addAll(arguments.map(_convertToJS));
+    var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
+    // Without this line, calling factoryFunction as a constructor throws
+    JS('String', 'String(#)', factoryFunction);
+    // 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);
   }
 
-  factory JsObject._json(data) => new JsObject._fromJs(_convertDataTree(data));
-
+  // TODO: handle cycles
   static _convertDataTree(data) {
-    if (data is Map) {
-      final convertedData = JS('=Object', '{}');
-      for (var key in data.keys) {
-        JS('=Object', '#[#]=#', convertedData, key,
-            _convertDataTree(data[key]));
+    var _convertedObjects = new HashMap.identity();
+
+    _convert(o) {
+      if (_convertedObjects.containsKey(o)) {
+        return _convertedObjects[o];
       }
-      return convertedData;
-    } else if (data is Iterable) {
-      return data.map(_convertDataTree).toList();
-    } else {
-      return _convertToJS(data);
+      if (o is Map) {
+        final convertedMap = JS('=Object', '{}');
+        _convertedObjects[o] = convertedMap;
+        for (var key in o.keys) {
+          JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
+        }
+        return convertedMap;
+      } else if (o is Iterable) {
+        var convertedList = [];
+        _convertedObjects[o] = convertedList;
+        convertedList.addAll(o.map(_convert));
+        return convertedList;
+      } else {
+        return _convertToJS(o);
+      }
     }
+
+    return _convert(data);
   }
 
-  JsObject toJs() => this;
-
-  operator[](key) =>
-      _convertToDart(JS('=Object', '#[#]', _convertToJS(this), key));
-
-  operator[]=(key, value) => JS('void', '#[#]=#', _convertToJS(this), key,
-      _convertToJS(value));
+  /**
+   * Returns the value associated with [key] from the proxied JavaScript
+   * object.
+   *
+   * [key] must either be a [String] or [num].
+   */
+  // TODO(justinfagnani): rename key/name to property
+  dynamic operator[](key) {
+    if (key is! String && key is! num) {
+      throw new ArgumentError("key is not a String or num");
+    }
+    return _convertToDart(JS('', '#[#]', _jsObject, key));
+  }
+  
+  /**
+   * Sets the value associated with [key] from the proxied JavaScript
+   * object.
+   *
+   * [key] must either be a [String] or [num].
+   */
+  operator[]=(key, value) {
+    if (key is! String && key is! num) {
+      throw new ArgumentError("key is not a String or num");
+    }
+    JS('', '#[#]=#', _jsObject, key, _convertToJS(value));
+  }
 
   int get hashCode => 0;
 
-  operator==(other) => other is JsObject &&
-      JS('bool', '# === #', _convertToJS(this), _convertToJS(other));
+  bool operator==(other) => other is JsObject &&
+      JS('bool', '# === #', _jsObject, other._jsObject);
 
-  bool hasProperty(String property) => JS('bool', '# in #', property,
-      _convertToJS(this));
-
-  void deleteProperty(String name) {
-    JS('void', 'delete #[#]', _convertToJS(this), name);
+  bool hasProperty(name) {
+    if (name is! String && name is! num) {
+      throw new ArgumentError("name is not a String or num");
+    }
+    return JS('bool', '# in #', name, _jsObject);
   }
 
-  // TODO(vsm): Type type as Serializable<JsFunction> when
-  // dartbug.com/11854 is fixed.
-  bool instanceof(var type) =>
-      JS('bool', '# instanceof #', _convertToJS(this), _convertToJS(type));
+  void deleteProperty(name) {
+    if (name is! String && name is! num) {
+      throw new ArgumentError("name is not a String or num");
+    }
+    JS('bool', 'delete #[#]', _jsObject, name);
+  }
+
+  bool instanceof(type) {
+    return JS('bool', '# instanceof #', _jsObject, _convertToJS(type));
+  }
 
   String toString() {
     try {
-      return JS('String', '#.toString()', _convertToJS(this));
+      return JS('String', 'String(#)', _jsObject);
     } catch(e) {
       return super.toString();
     }
   }
 
-  callMethod(String name, [List args]) =>
-      _convertToDart(JS('=Object', '#[#].apply(#, #)', _convertToJS(this), name,
-          _convertToJS(this),
-          args == null ? null : args.map(_convertToJS).toList()));
+  dynamic callMethod(name, [List args]) {
+    if (name is! String && name is! num) {
+      throw new ArgumentError("name is not a String or num");
+    }
+    return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, name,
+        _jsObject,
+        args == null ? null : args.map(_convertToJS).toList()));
+  }
 }
 
-class JsFunction extends JsObject implements Serializable<JsFunction> {
+class JsFunction extends JsObject {
+
+  /**
+   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
+   * with the value of this passed as the first argument.
+   */
+  factory JsFunction.withThis(Function f) {
+    var jsFunc = _convertDartFunction(f, captureThis: true);
+    return new JsFunction._fromJs(jsFunc);
+  }
+
   JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
-  apply(thisArg, [List args]) =>
-      _convertToDart(JS('=Object', '#.apply(#, #)', _convertToJS(this),
+
+  dynamic apply(List args, { thisArg }) =>
+      _convertToDart(JS('', '#.apply(#, #)', _jsObject,
           _convertToJS(thisArg),
           args == null ? null : args.map(_convertToJS).toList()));
 }
 
-abstract class Serializable<T> {
-  T toJs();
-}
-
 // property added to a Dart object referencing its JS-side DartObject proxy
 const _DART_OBJECT_PROPERTY_NAME = r'_$dart_dartObject';
 const _DART_CLOSURE_PROPERTY_NAME = r'_$dart_dartClosure';
@@ -222,12 +234,14 @@
 dynamic _convertToJS(dynamic o) {
   if (o == null) {
     return null;
-  } else if (o is String || o is num || o is bool) {
+  } 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) {
     return o;
+  } else if (o is DateTime) {
+    return Primitives.lazyAsJsDate(o);
   } else if (o is JsObject) {
     return o._jsObject;
-  } else if (o is Serializable) {
-    return _convertToJS(o.toJs());
   } else if (o is Function) {
     return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) {
       var jsFunction = _convertDartFunction(o);
@@ -241,7 +255,7 @@
   }
 }
 
-dynamic _getJsProxy(o, String propertyName, createProxy(o)) {
+Object _getJsProxy(o, String propertyName, createProxy(o)) {
   var jsProxy = JS('', '#[#]', o, propertyName);
   if (jsProxy == null) {
     jsProxy = createProxy(o);
@@ -252,25 +266,27 @@
 
 // converts a Dart object to a reference to a native JS object
 // which might be a DartObject JS->Dart proxy
-dynamic _convertToDart(dynamic o) {
-  if (JS('bool', '# == null', o)) {
-    return null;
-  } else if (JS('bool', 'typeof # == "string" || # instanceof String', o, o) ||
-      JS('bool', 'typeof # == "number" || # instanceof Number', o, o) ||
-      JS('bool', 'typeof # == "boolean" || # instanceof Boolean', o, o)) {
+Object _convertToDart(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 (JS('bool', '# instanceof Function', o)) {
+  } else if (o is Blob || o is DateTime || o is KeyRange 
+      || o is ImageData || o is Node || o is TypedData) {
+    return JS('Blob|DateTime|KeyRange|ImageData|Node|TypedData', '#', o);
+  } else if (JS('bool', 'typeof # == "function"', o)) {
     return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME,
         (o) => new JsFunction._fromJs(o));
-  } else if (JS('bool', '# instanceof DartObject', o)) {
-    return JS('var', '#.o', o);
+  } else if (JS('bool', '#.constructor === DartObject', o)) {
+    return JS('', '#.o', o);
   } else {
     return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME,
         (o) => new JsObject._fromJs(o));
   }
 }
 
-dynamic _getDartProxy(o, String propertyName, createProxy(o)) {
+Object _getDartProxy(o, String propertyName, createProxy(o)) {
   var dartProxy = JS('', '#[#]', o, propertyName);
   if (dartProxy == null) {
     dartProxy = createProxy(o);
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index 234a4bf..8cc3928 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -2,419 +2,114 @@
 // 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 js.dart library provides simple JavaScript invocation from Dart that
- * works on both Dartium and on other modern browsers via Dart2JS.
- *
- * It provides a model based on scoped [JsObject] objects.  Proxies give Dart
- * code access to JavaScript objects, fields, and functions as well as the
- * ability to pass Dart objects and functions to JavaScript functions.  Scopes
- * enable developers to use proxies without memory leaks - a common challenge
- * with cross-runtime interoperation.
- *
- * The top-level [context] getter provides a [JsObject] to the global JavaScript
- * context for the page your Dart code is running on.  In the following example:
- *
- *     import 'dart:js';
- *
- *     void main() {
- *       context.callMethod('alert', ['Hello from Dart via JavaScript']);
- *     }
- *
- * context['alert'] creates a proxy to the top-level alert function in
- * JavaScript.  It is invoked from Dart as a regular function that forwards to
- * the underlying JavaScript one.  By default, proxies are released when
- * the currently executing event completes, e.g., when main is completes
- * in this example.
- *
- * The library also enables JavaScript proxies to Dart objects and functions.
- * For example, the following Dart code:
- *
- *     context['dartCallback'] = new Callback.once((x) => print(x*2));
- *
- * defines a top-level JavaScript function 'dartCallback' that is a proxy to
- * the corresponding Dart function.  The [Callback.once] constructor allows the
- * proxy to the Dart function to be retained across multiple events;
- * instead it is released after the first invocation.  (This is a common
- * pattern for asychronous callbacks.)
- *
- * Note, parameters and return values are intuitively passed by value for
- * primitives and by reference for non-primitives.  In the latter case, the
- * references are automatically wrapped and unwrapped as proxies by the library.
- *
- * This library also allows construction of JavaScripts objects given a
- * [JsObject] to a corresponding JavaScript constructor.  For example, if the
- * following JavaScript is loaded on the page:
- *
- *     function Foo(x) {
- *       this.x = x;
- *     }
- *
- *     Foo.prototype.add = function(other) {
- *       return new Foo(this.x + other.x);
- *     }
- *
- * then, the following Dart:
- *
- *     var foo = new JsObject(context['Foo'], [42]);
- *     var foo2 = foo.callMethod('add', [foo]);
- *     print(foo2['x']);
- *
- * will construct a JavaScript Foo object with the parameter 42, invoke its
- * add method, and return a [JsObject] to a new Foo object whose x field is 84.
- */
-
 library dart.js;
 
-import 'dart:collection' show HashMap;
-import 'dart:html';
-import 'dart:isolate';
+import 'dart:nativewrappers';
 
-// Global ports to manage communication from Dart to JS.
+JsObject _cachedContext;
 
-SendPortSync _jsPortSync = window.lookupPort('dart-js-context');
-SendPortSync _jsPortCreate = window.lookupPort('dart-js-create');
-SendPortSync _jsPortInstanceof = window.lookupPort('dart-js-instanceof');
-SendPortSync _jsPortDeleteProperty = window.lookupPort('dart-js-delete-property');
-SendPortSync _jsPortConvert = window.lookupPort('dart-js-convert');
+JsObject get _context native "Js_context_Callback";
 
-final String _objectIdPrefix = 'dart-obj-ref';
-final String _functionIdPrefix = 'dart-fun-ref';
-final _objectTable = new _ObjectTable();
-final _functionTable = new _ObjectTable.forFunctions();
-
-// Port to handle and forward requests to the underlying Dart objects.
-// A remote proxy is uniquely identified by an ID and SendPortSync.
-ReceivePortSync _port = new ReceivePortSync()
-    ..receive((msg) {
-      try {
-        var id = msg[0];
-        var method = msg[1];
-        if (method == '#call') {
-          var receiver = _getObjectTable(id).get(id);
-          var result;
-          if (receiver is Function) {
-            // remove the first argument, which is 'this', but never
-            // used for a raw function
-            var args = msg[2].sublist(1).map(_deserialize).toList();
-            result = Function.apply(receiver, args);
-          } else if (receiver is Callback) {
-            var args = msg[2].map(_deserialize).toList();
-            result = receiver._call(args);
-          } else {
-            throw new StateError('bad function type: $receiver');
-          }
-          return ['return', _serialize(result)];
-        } else {
-          // TODO(vsm): Support a mechanism to register a handler here.
-          throw 'Invocation unsupported on non-function Dart proxies';
-        }
-      } catch (e) {
-        // TODO(vsm): callSync should just handle exceptions itself.
-        return ['throws', '$e'];
-      }
-    });
-
-_ObjectTable _getObjectTable(String id) {
-  if (id.startsWith(_functionIdPrefix)) return _functionTable;
-  if (id.startsWith(_objectIdPrefix)) return _objectTable;
-  throw new ArgumentError('internal error: invalid object id: $id');
-}
-
-JsObject _context;
-
-/**
- * Returns a proxy to the global JavaScript context for this page.
- */
 JsObject get context {
-  if (_context == null) {
-    var port = _jsPortSync;
-    if (port == null) {
-      return null;
-    }
-    _context = _deserialize(_jsPortSync.callSync([]));
+  if (_cachedContext == null) {
+    _cachedContext = _context;
   }
-  return _context;
+  return _cachedContext;
 }
 
-/**
- * Converts a json-like [data] to a JavaScript map or array and return a
- * [JsObject] to it.
- */
-JsObject jsify(dynamic data) => data == null ? null : new JsObject._json(data);
+class JsObject extends NativeFieldWrapperClass2 {
+  JsObject.internal();
 
-/**
- * Converts a local Dart function to a callback that can be passed to
- * JavaScript.
- */
-class Callback implements Serializable<JsFunction> {
-  final bool _withThis;
-  final Function _function;
-  JsFunction _jsFunction;
+  factory JsObject(JsFunction constructor, [List arguments]) => _create(constructor, arguments);
 
-  Callback._(this._function, this._withThis) {
-    var id = _functionTable.add(this);
-    _jsFunction = new JsFunction._internal(_port.toSendPort(), id);
-  }
+  static JsObject _create(JsFunction constructor, arguments) native "JsObject_constructorCallback";
 
-  factory Callback(Function f) => new Callback._(f, false);
-  factory Callback.withThis(Function f) => new Callback._(f, true);
-
-  dynamic _call(List args) {
-    var arguments = (_withThis) ? args : args.sublist(1);
-    return Function.apply(_function, arguments);
-  }
-
-  JsFunction toJs() => _jsFunction;
-}
-
-/**
- * Proxies to JavaScript objects.
- */
-class JsObject implements Serializable<JsObject> {
-  final SendPortSync _port;
-  final String _id;
-
-  /**
-   * Constructs a [JsObject] to a new JavaScript object by invoking a (proxy to
-   * a) JavaScript [constructor].  The [arguments] list should contain either
-   * primitive values, DOM elements, or Proxies.
-   */
-  factory JsObject(Serializable<JsFunction> constructor, [List arguments]) {
-    final params = [constructor];
-    if (arguments != null) params.addAll(arguments);
-    final serialized = params.map(_serialize).toList();
-    final result = _jsPortCreate.callSync(serialized);
-    return _deserialize(result);
-  }
-
-  /**
-   * Constructs a [JsObject] to a new JavaScript map or list created defined via
-   * Dart map or list.
-   */
-  factory JsObject._json(data) => _convert(data);
-
-  static _convert(data) =>
-      _deserialize(_jsPortConvert.callSync(_serializeDataTree(data)));
-
-  static _serializeDataTree(data) {
-    if (data is Map) {
-      final entries = new List();
-      for (var key in data.keys) {
-        entries.add([key, _serializeDataTree(data[key])]);
-      }
-      return ['map', entries];
-    } else if (data is Iterable) {
-      return ['list', data.map(_serializeDataTree).toList()];
-    } else {
-      return ['simple', _serialize(data)];
+   /**
+    * Expert users only:
+    * Use this constructor only if you want to gain access to JS expandos
+    * attached to a browser native object such as a Node.
+    * Not all native browser objects can be converted using fromBrowserObject.
+    * Currently the following types are supported:
+    * * Node
+    * * ArrayBuffer
+    * * Blob
+    * * ImageData
+    * * IDBKeyRange
+    * TODO(jacobr): support Event, Window and NodeList as well.
+    */
+  factory JsObject.fromBrowserObject(var object) {
+    if (object is num || object is String || object is bool || object == null) {
+      throw new ArgumentError(
+        "object cannot be a num, string, bool, or null");
     }
-  }
-
-  JsObject._internal(this._port, this._id);
-
-  JsObject toJs() => this;
-
-  // Resolve whether this is needed.
-  operator[](arg) => _forward(this, '[]', 'method', [ arg ]);
-
-  // Resolve whether this is needed.
-  operator[]=(key, value) => _forward(this, '[]=', 'method', [ key, value ]);
-
-  int get hashCode => _id.hashCode;
-
-  // Test if this is equivalent to another Proxy.  This essentially
-  // maps to JavaScript's === operator.
-  operator==(other) => other is JsObject && this._id == other._id;
-
-  /**
-   * Check if this [JsObject] has a [name] property.
-   */
-  bool hasProperty(String name) => _forward(this, name, 'hasProperty', []);
-
-  /**
-   * Delete the [name] property.
-   */
-  void deleteProperty(String name) {
-    _jsPortDeleteProperty.callSync([this, name].map(_serialize).toList());
+    return _fromBrowserObject(object);
   }
 
   /**
-   * Check if this [JsObject] is instance of [type].
+   * Converts a json-like [object] to a JavaScript map or array and return a
+   * [JsObject] to it.
    */
-  bool instanceof(Serializable<JsFunction> type) =>
-      _jsPortInstanceof.callSync([this, type].map(_serialize).toList());
+  factory JsObject.jsify(object) {
+    if ((object is! Map) && (object is! Iterable)) {
+      throw new ArgumentError("object must be a Map or Iterable");
+    }
+    return _jsify(object);
+  }
+
+  static JSObject _jsify(object) native "JsObject_jsify";
+
+  static JsObject _fromBrowserObject(object) native "JsObject_fromBrowserObject";
+
+  operator[](key) native "JsObject_[]";
+  operator[]=(key, value) native "JsObject_[]=";
+
+  int get hashCode native "JsObject_hashCode";
+
+  operator==(other) => other is JsObject && _identityEquality(this, other);
+
+  static bool _identityEquality(JsObject a, JsObject b) native "JsObject_identityEquality";
+
+  bool hasProperty(String property) native "JsObject_hasProperty";
+
+  void deleteProperty(JsFunction name) native "JsObject_deleteProperty";
+
+  bool instanceof(JsFunction type) native "JsObject_instanceof";
 
   String toString() {
     try {
-      return _forward(this, 'toString', 'method', []);
+      return _toString();
     } catch(e) {
       return super.toString();
     }
   }
 
+  String _toString() native "JsObject_toString";
+
   callMethod(String name, [List args]) {
-    return _forward(this, name, 'method', args != null ? args : []);
-  }
-
-  // Forward member accesses to the backing JavaScript object.
-  static _forward(JsObject receiver, String member, String kind, List args) {
-    var result = receiver._port.callSync([receiver._id, member, kind,
-                                          args.map(_serialize).toList()]);
-    switch (result[0]) {
-      case 'return': return _deserialize(result[1]);
-      case 'throws': throw _deserialize(result[1]);
-      case 'none':
-          throw new NoSuchMethodError(receiver, new Symbol(member), args, {});
-      default: throw 'Invalid return value';
-    }
-  }
-}
-
-/// A [JsObject] subtype to JavaScript functions.
-class JsFunction extends JsObject implements Serializable<JsFunction> {
-  JsFunction._internal(SendPortSync port, String id)
-      : super._internal(port, id);
-
-  apply(thisArg, [List args]) {
-    return JsObject._forward(this, '', 'apply',
-        [thisArg]..addAll(args == null ? [] : args));
-  }
-}
-
-/// Marker class used to indicate it is serializable to js. If a class is a
-/// [Serializable] the "toJs" method will be called and the result will be used
-/// as value.
-abstract class Serializable<T> {
-  T toJs();
-}
-
-class _ObjectTable {
-  final String name;
-  final Map<String, Object> objects;
-  final Map<Object, String> ids;
-  int nextId = 0;
-
-  // Creates a table that uses an identity Map to store IDs
-  _ObjectTable()
-    : name = _objectIdPrefix,
-      objects = new HashMap<String, Object>(),
-      ids = new HashMap<Object, String>.identity();
-
-  // Creates a table that uses an equality-based Map to store IDs, since
-  // closurized methods may be equal, but not identical
-  _ObjectTable.forFunctions()
-    : name = _functionIdPrefix,
-      objects = new HashMap<String, Object>(),
-      ids = new HashMap<Object, String>();
-
-  // Adds a new object to the table. If [id] is not given, a new unique ID is
-  // generated. Returns the ID.
-  String add(Object o, {String id}) {
-    // TODO(vsm): Cache x and reuse id.
-    if (id == null) id = ids[o];
-    if (id == null) id = '$name-${nextId++}';
-    ids[o] = id;
-    objects[id] = o;
-    return id;
-  }
-
-  // Gets an object by ID.
-  Object get(String id) => objects[id];
-
-  bool contains(String id) => objects.containsKey(id);
-
-  String getId(Object o) => ids[o];
-
-  // Gets the current number of objects kept alive by this table.
-  get count => objects.length;
-}
-
-// Dart serialization support.
-
-_serialize(var message) {
-  if (message == null) {
-    return null;  // Convert undefined to null.
-  } else if (message is String ||
-             message is num ||
-             message is bool) {
-    // Primitives are passed directly through.
-    return message;
-  } else if (message is SendPortSync) {
-    // Non-proxied objects are serialized.
-    return message;
-  } else if (message is JsFunction) {
-    // Remote function proxy.
-    return ['funcref', message._id, message._port];
-  } else if (message is JsObject) {
-    // Remote object proxy.
-    return ['objref', message._id, message._port];
-  } else if (message is Serializable) {
-    // use of result of toJs()
-    return _serialize(message.toJs());
-  } else if (message is Function) {
-    var id = _functionTable.getId(message);
-    if (id != null) {
-      return ['funcref', id, _port.toSendPort()];
-    }
-    id = _functionTable.add(message);
-    return ['funcref', id, _port.toSendPort()];
-  } else {
-    // Local object proxy.
-    return ['objref', _objectTable.add(message), _port.toSendPort()];
-  }
-}
-
-_deserialize(var message) {
-  deserializeFunction(message) {
-    var id = message[1];
-    var port = message[2];
-    if (port == _port.toSendPort()) {
-      // Local function.
-      return _functionTable.get(id);
-    } else {
-      // Remote function.
-      var jsFunction = _functionTable.get(id);
-      if (jsFunction == null) {
-        jsFunction = new JsFunction._internal(port, id);
-        _functionTable.add(jsFunction, id: id);
+    try {
+      return _callMethod(name, args);
+    } catch(e) {
+      if (hasProperty(name)) {
+        rethrow;
+      } else {
+        throw new NoSuchMethodError(this, new Symbol(name), args, null);
       }
-      return jsFunction;
     }
   }
 
-  deserializeObject(message) {
-    var id = message[1];
-    var port = message[2];
-    if (port == _port.toSendPort()) {
-      // Local object.
-      return _objectTable.get(id);
-    } else {
-      // Remote object.
-      var jsObject = _objectTable.get(id);
-      if (jsObject == null) {
-        jsObject = new JsObject._internal(port, id);
-        _objectTable.add(jsObject, id: id);
-      }
-      return jsObject;
-    }
-  }
+  _callMethod(String name, List args) native "JsObject_callMethod";
+}
 
-  if (message == null) {
-    return null;  // Convert undefined to null.
-  } else if (message is String ||
-             message is num ||
-             message is bool) {
-    // Primitives are passed directly through.
-    return message;
-  } else if (message is SendPortSync) {
-    // Serialized type.
-    return message;
-  }
-  var tag = message[0];
-  switch (tag) {
-    case 'funcref': return deserializeFunction(message);
-    case 'objref': return deserializeObject(message);
-  }
-  throw 'Unsupported serialized data: $message';
+class JsFunction extends JsObject {
+  JsFunction.internal();
+
+  /**
+   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
+   * with the value of this passed as the first argument.
+   */
+  factory JsFunction.withThis(Function f) => _withThis(f);
+
+  apply(List args, {thisArg}) native "JsFunction_apply";
+
+  static JsFunction _withThis(Function f) native "JsFunction_withThis";
 }
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index b35e0ff..eddaa77 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -150,8 +150,8 @@
  * This function returns a [ClassMirror] reflecting *C*.
  *
  * If [key] is not an instance of [Type] then this function
- * throws an [ArgumentError]. If [key] is the Type [:dynamic:],
- * throws an [ArgumentError] because dynamic is not a class.
+ * throws an [ArgumentError]. If [key] is the Type for dynamic
+ * or a function typedef, throws an [ArgumentError].
  *
  * Note that since one cannot obtain a [Type] object from
  * another isolate, this function can only be used to
@@ -160,6 +160,19 @@
 external ClassMirror reflectClass(Type key);
 
 /**
+ * This function returns a [TypeMirror] reflecting the type
+ * represented by [key].
+ *
+ * If [key] is not an instance of [Type] then this function
+ * throws an [ArgumentError].
+ *
+ * Note that since one cannot obtain a [Type] object from
+ * another isolate, this function can only be used to
+ * obtain type mirrors on types of the current isolate.
+ */
+external TypeMirror reflectType(Type key);
+
+/**
  * A [Mirror] reflects some Dart language entity.
  *
  * Every [Mirror] originates from some [MirrorSystem].
@@ -678,6 +691,12 @@
   Map<Symbol, ClassMirror> get classes;
 
   /**
+   * An immutable map from names to mirrors for all type
+   * declarations in this library.
+   */
+  Map<Symbol, TypeMirror> get types;
+
+  /**
    * An immutable map from names to mirrors for all function, getter,
    * and setter declarations in this library.
    */
@@ -753,8 +772,7 @@
   /**
    * A mirror on the superclass on the reflectee.
    *
-   * If this type is [:Object:] or a typedef, the superClass will be
-   * null.
+   * If this type is [:Object:], the superclass will be null.
    */
   ClassMirror get superclass;
 
@@ -985,13 +1003,13 @@
 /**
  * A [TypedefMirror] represents a typedef in a Dart language program.
  */
-abstract class TypedefMirror implements ClassMirror {
+abstract class TypedefMirror implements TypeMirror {
   /**
    * The defining type for this typedef.
    *
-   * For instance [:void f(int):] is the value for [:typedef void f(int):].
+   * For instance [:void f(int):] is the referent for [:typedef void f(int):].
    */
-  TypeMirror get value;
+  TypeMirror get referent;
 }
 
 /**
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index e92e1b4..0b8bea3 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -123,7 +123,7 @@
 @DocsEditable()
 @DomName('SVGAngle')
 @Unstable()
-class Angle extends NativeFieldWrapperClass1 {
+class Angle extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Angle._() { throw new UnsupportedError("Not supported"); }
 
@@ -287,7 +287,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedAngle')
 @Unstable()
-class AnimatedAngle extends NativeFieldWrapperClass1 {
+class AnimatedAngle extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedAngle._() { throw new UnsupportedError("Not supported"); }
 
@@ -310,7 +310,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedBoolean')
 @Unstable()
-class AnimatedBoolean extends NativeFieldWrapperClass1 {
+class AnimatedBoolean extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedBoolean._() { throw new UnsupportedError("Not supported"); }
 
@@ -337,7 +337,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedEnumeration')
 @Unstable()
-class AnimatedEnumeration extends NativeFieldWrapperClass1 {
+class AnimatedEnumeration extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedEnumeration._() { throw new UnsupportedError("Not supported"); }
 
@@ -364,7 +364,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedInteger')
 @Unstable()
-class AnimatedInteger extends NativeFieldWrapperClass1 {
+class AnimatedInteger extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedInteger._() { throw new UnsupportedError("Not supported"); }
 
@@ -391,7 +391,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedLength')
 @Unstable()
-class AnimatedLength extends NativeFieldWrapperClass1 {
+class AnimatedLength extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedLength._() { throw new UnsupportedError("Not supported"); }
 
@@ -414,7 +414,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedLengthList')
 @Unstable()
-class AnimatedLengthList extends NativeFieldWrapperClass1 {
+class AnimatedLengthList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedLengthList._() { throw new UnsupportedError("Not supported"); }
 
@@ -437,7 +437,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedNumber')
 @Unstable()
-class AnimatedNumber extends NativeFieldWrapperClass1 {
+class AnimatedNumber extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedNumber._() { throw new UnsupportedError("Not supported"); }
 
@@ -464,7 +464,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedNumberList')
 @Unstable()
-class AnimatedNumberList extends NativeFieldWrapperClass1 {
+class AnimatedNumberList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedNumberList._() { throw new UnsupportedError("Not supported"); }
 
@@ -487,7 +487,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedPreserveAspectRatio')
 @Unstable()
-class AnimatedPreserveAspectRatio extends NativeFieldWrapperClass1 {
+class AnimatedPreserveAspectRatio extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedPreserveAspectRatio._() { throw new UnsupportedError("Not supported"); }
 
@@ -510,7 +510,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedRect')
 @Unstable()
-class AnimatedRect extends NativeFieldWrapperClass1 {
+class AnimatedRect extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedRect._() { throw new UnsupportedError("Not supported"); }
 
@@ -533,7 +533,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedString')
 @Unstable()
-class AnimatedString extends NativeFieldWrapperClass1 {
+class AnimatedString extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedString._() { throw new UnsupportedError("Not supported"); }
 
@@ -560,7 +560,7 @@
 @DocsEditable()
 @DomName('SVGAnimatedTransformList')
 @Unstable()
-class AnimatedTransformList extends NativeFieldWrapperClass1 {
+class AnimatedTransformList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AnimatedTransformList._() { throw new UnsupportedError("Not supported"); }
 
@@ -1239,7 +1239,7 @@
 @DocsEditable()
 @DomName('SVGExternalResourcesRequired')
 @Unstable()
-abstract class ExternalResourcesRequired extends NativeFieldWrapperClass1 {
+abstract class ExternalResourcesRequired extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ExternalResourcesRequired._() { throw new UnsupportedError("Not supported"); }
 
@@ -2855,7 +2855,7 @@
 @DocsEditable()
 @DomName('SVGFilterPrimitiveStandardAttributes')
 @Unstable()
-abstract class FilterPrimitiveStandardAttributes extends NativeFieldWrapperClass1 {
+abstract class FilterPrimitiveStandardAttributes extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory FilterPrimitiveStandardAttributes._() { throw new UnsupportedError("Not supported"); }
 
@@ -2890,7 +2890,7 @@
 @DocsEditable()
 @DomName('SVGFitToViewBox')
 @Unstable()
-abstract class FitToViewBox extends NativeFieldWrapperClass1 {
+abstract class FitToViewBox extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory FitToViewBox._() { throw new UnsupportedError("Not supported"); }
 
@@ -3122,7 +3122,7 @@
 @DocsEditable()
 @DomName('SVGLength')
 @Unstable()
-class Length extends NativeFieldWrapperClass1 {
+class Length extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Length._() { throw new UnsupportedError("Not supported"); }
 
@@ -3217,7 +3217,7 @@
 @DocsEditable()
 @DomName('SVGLengthList')
 @Unstable()
-class LengthList extends NativeFieldWrapperClass1 with ListMixin<Length>, ImmutableListMixin<Length> implements List {
+class LengthList extends NativeFieldWrapperClass2 with ListMixin<Length>, ImmutableListMixin<Length> implements List {
   // To suppress missing implicit constructor warnings.
   factory LengthList._() { throw new UnsupportedError("Not supported"); }
 
@@ -3562,7 +3562,7 @@
 @DocsEditable()
 @DomName('SVGMatrix')
 @Unstable()
-class Matrix extends NativeFieldWrapperClass1 {
+class Matrix extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Matrix._() { throw new UnsupportedError("Not supported"); }
 
@@ -3690,7 +3690,7 @@
 @DocsEditable()
 @DomName('SVGNumber')
 @Unstable()
-class Number extends NativeFieldWrapperClass1 {
+class Number extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Number._() { throw new UnsupportedError("Not supported"); }
 
@@ -3713,7 +3713,7 @@
 @DocsEditable()
 @DomName('SVGNumberList')
 @Unstable()
-class NumberList extends NativeFieldWrapperClass1 with ListMixin<Number>, ImmutableListMixin<Number> implements List {
+class NumberList extends NativeFieldWrapperClass2 with ListMixin<Number>, ImmutableListMixin<Number> implements List {
   // To suppress missing implicit constructor warnings.
   factory NumberList._() { throw new UnsupportedError("Not supported"); }
 
@@ -3943,7 +3943,7 @@
 @DocsEditable()
 @DomName('SVGPathSeg')
 @Unstable()
-class PathSeg extends NativeFieldWrapperClass1 {
+class PathSeg extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PathSeg._() { throw new UnsupportedError("Not supported"); }
 
@@ -4733,7 +4733,7 @@
 @DocsEditable()
 @DomName('SVGPathSegList')
 @Unstable()
-class PathSegList extends NativeFieldWrapperClass1 with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List {
+class PathSegList extends NativeFieldWrapperClass2 with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List {
   // To suppress missing implicit constructor warnings.
   factory PathSegList._() { throw new UnsupportedError("Not supported"); }
 
@@ -4973,7 +4973,7 @@
 @DocsEditable()
 @DomName('SVGPoint')
 @Unstable()
-class Point extends NativeFieldWrapperClass1 {
+class Point extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Point._() { throw new UnsupportedError("Not supported"); }
 
@@ -5008,7 +5008,7 @@
 @DocsEditable()
 @DomName('SVGPointList')
 @Unstable()
-class PointList extends NativeFieldWrapperClass1 {
+class PointList extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PointList._() { throw new UnsupportedError("Not supported"); }
 
@@ -5129,7 +5129,7 @@
 @DocsEditable()
 @DomName('SVGPreserveAspectRatio')
 @Unstable()
-class PreserveAspectRatio extends NativeFieldWrapperClass1 {
+class PreserveAspectRatio extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PreserveAspectRatio._() { throw new UnsupportedError("Not supported"); }
 
@@ -5265,7 +5265,7 @@
 @DocsEditable()
 @DomName('SVGRect')
 @Unstable()
-class Rect extends NativeFieldWrapperClass1 {
+class Rect extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Rect._() { throw new UnsupportedError("Not supported"); }
 
@@ -5365,7 +5365,7 @@
 @DocsEditable()
 @DomName('SVGRenderingIntent')
 @Unstable()
-class RenderingIntent extends NativeFieldWrapperClass1 {
+class RenderingIntent extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory RenderingIntent._() { throw new UnsupportedError("Not supported"); }
 
@@ -5505,7 +5505,7 @@
 @DocsEditable()
 @DomName('SVGStringList')
 @Unstable()
-class StringList extends NativeFieldWrapperClass1 with ListMixin<String>, ImmutableListMixin<String> implements List {
+class StringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List {
   // To suppress missing implicit constructor warnings.
   factory StringList._() { throw new UnsupportedError("Not supported"); }
 
@@ -6186,7 +6186,7 @@
 @DocsEditable()
 @DomName('SVGTests')
 @Unstable()
-abstract class Tests extends NativeFieldWrapperClass1 {
+abstract class Tests extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Tests._() { throw new UnsupportedError("Not supported"); }
 
@@ -6450,7 +6450,7 @@
 @DocsEditable()
 @DomName('SVGTransform')
 @Unstable()
-class Transform extends NativeFieldWrapperClass1 {
+class Transform extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Transform._() { throw new UnsupportedError("Not supported"); }
 
@@ -6529,7 +6529,7 @@
 @DocsEditable()
 @DomName('SVGTransformList')
 @Unstable()
-class TransformList extends NativeFieldWrapperClass1 with ListMixin<Transform>, ImmutableListMixin<Transform> implements List {
+class TransformList extends NativeFieldWrapperClass2 with ListMixin<Transform>, ImmutableListMixin<Transform> implements List {
   // To suppress missing implicit constructor warnings.
   factory TransformList._() { throw new UnsupportedError("Not supported"); }
 
@@ -6630,7 +6630,7 @@
 @DocsEditable()
 @DomName('SVGUnitTypes')
 @Unstable()
-class UnitTypes extends NativeFieldWrapperClass1 {
+class UnitTypes extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory UnitTypes._() { throw new UnsupportedError("Not supported"); }
 
@@ -6657,7 +6657,7 @@
 @DocsEditable()
 @DomName('SVGURIReference')
 @Unstable()
-abstract class UriReference extends NativeFieldWrapperClass1 {
+abstract class UriReference extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory UriReference._() { throw new UnsupportedError("Not supported"); }
 
@@ -6798,7 +6798,7 @@
 @DocsEditable()
 @DomName('SVGViewSpec')
 @Unstable()
-class ViewSpec extends NativeFieldWrapperClass1 implements FitToViewBox {
+class ViewSpec extends NativeFieldWrapperClass2 implements FitToViewBox {
   // To suppress missing implicit constructor warnings.
   factory ViewSpec._() { throw new UnsupportedError("Not supported"); }
 
@@ -6857,7 +6857,7 @@
 @DocsEditable()
 @DomName('SVGZoomAndPan')
 @Unstable()
-abstract class ZoomAndPan extends NativeFieldWrapperClass1 {
+abstract class ZoomAndPan extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ZoomAndPan._() { throw new UnsupportedError("Not supported"); }
 
@@ -6927,7 +6927,7 @@
 @DocsEditable()
 @DomName('SVGElementInstanceList')
 @Unstable()
-class _ElementInstanceList extends NativeFieldWrapperClass1 with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List {
+class _ElementInstanceList extends NativeFieldWrapperClass2 with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List {
   // To suppress missing implicit constructor warnings.
   factory _ElementInstanceList._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index a7aa32a..18dfce2 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -229,7 +229,7 @@
 @DomName('AudioContext')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioContext-section
 @Experimental()
-class AudioContext extends EventTarget native "AudioContext" {
+class AudioContext extends EventTarget native "AudioContext,webkitAudioContext" {
   // To suppress missing implicit constructor warnings.
   factory AudioContext._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index 5568efa..c33212c 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -88,7 +88,7 @@
 @DomName('AudioBuffer')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioBuffer-section
 @Experimental()
-class AudioBuffer extends NativeFieldWrapperClass1 {
+class AudioBuffer extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AudioBuffer._() { throw new UnsupportedError("Not supported"); }
 
@@ -510,7 +510,7 @@
 @DomName('AudioListener')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioListener-section
 @Experimental()
-class AudioListener extends NativeFieldWrapperClass1 {
+class AudioListener extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AudioListener._() { throw new UnsupportedError("Not supported"); }
 
@@ -642,7 +642,7 @@
 @DomName('AudioParam')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioParam
 @Experimental()
-class AudioParam extends NativeFieldWrapperClass1 {
+class AudioParam extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AudioParam._() { throw new UnsupportedError("Not supported"); }
 
@@ -1320,7 +1320,7 @@
 @DocsEditable()
 @DomName('PeriodicWave')
 @Experimental() // untriaged
-class PeriodicWave extends NativeFieldWrapperClass1 {
+class PeriodicWave extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory PeriodicWave._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index 52678dc..aa4703c 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -325,7 +325,7 @@
 @DocsEditable()
 @DomName('WebGLActiveInfo')
 @Unstable()
-class ActiveInfo extends NativeFieldWrapperClass1 {
+class ActiveInfo extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ActiveInfo._() { throw new UnsupportedError("Not supported"); }
 
@@ -352,7 +352,7 @@
 @DocsEditable()
 @DomName('ANGLEInstancedArrays')
 @Experimental() // untriaged
-class AngleInstancedArrays extends NativeFieldWrapperClass1 {
+class AngleInstancedArrays extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory AngleInstancedArrays._() { throw new UnsupportedError("Not supported"); }
 
@@ -387,7 +387,7 @@
 @DocsEditable()
 @DomName('WebGLBuffer')
 @Unstable()
-class Buffer extends NativeFieldWrapperClass1 {
+class Buffer extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Buffer._() { throw new UnsupportedError("Not supported"); }
 
@@ -403,7 +403,7 @@
 @DomName('WebGLCompressedTextureATC')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/
 @Experimental()
-class CompressedTextureAtc extends NativeFieldWrapperClass1 {
+class CompressedTextureAtc extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CompressedTextureAtc._() { throw new UnsupportedError("Not supported"); }
 
@@ -431,7 +431,7 @@
 @DomName('WebGLCompressedTexturePVRTC')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/
 @Experimental() // experimental
-class CompressedTexturePvrtc extends NativeFieldWrapperClass1 {
+class CompressedTexturePvrtc extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CompressedTexturePvrtc._() { throw new UnsupportedError("Not supported"); }
 
@@ -463,7 +463,7 @@
 @DomName('WebGLCompressedTextureS3TC')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
 @Experimental() // experimental
-class CompressedTextureS3TC extends NativeFieldWrapperClass1 {
+class CompressedTextureS3TC extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory CompressedTextureS3TC._() { throw new UnsupportedError("Not supported"); }
 
@@ -494,7 +494,7 @@
 @DocsEditable()
 @DomName('WebGLContextAttributes')
 @Unstable()
-class ContextAttributes extends NativeFieldWrapperClass1 {
+class ContextAttributes extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ContextAttributes._() { throw new UnsupportedError("Not supported"); }
 
@@ -577,7 +577,7 @@
 @DomName('WebGLDebugRendererInfo')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_renderer_info/
 @Experimental() // experimental
-class DebugRendererInfo extends NativeFieldWrapperClass1 {
+class DebugRendererInfo extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DebugRendererInfo._() { throw new UnsupportedError("Not supported"); }
 
@@ -601,7 +601,7 @@
 @DomName('WebGLDebugShaders')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_shaders/
 @Experimental() // experimental
-class DebugShaders extends NativeFieldWrapperClass1 {
+class DebugShaders extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DebugShaders._() { throw new UnsupportedError("Not supported"); }
 
@@ -621,7 +621,7 @@
 @DomName('WebGLDepthTexture')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/
 @Experimental() // experimental
-class DepthTexture extends NativeFieldWrapperClass1 {
+class DepthTexture extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DepthTexture._() { throw new UnsupportedError("Not supported"); }
 
@@ -641,7 +641,7 @@
 @DomName('WebGLDrawBuffers')
 // http://www.khronos.org/registry/webgl/specs/latest/
 @Experimental() // stable
-class DrawBuffers extends NativeFieldWrapperClass1 {
+class DrawBuffers extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory DrawBuffers._() { throw new UnsupportedError("Not supported"); }
 
@@ -797,7 +797,7 @@
 @DomName('EXTFragDepth')
 // http://www.khronos.org/registry/webgl/extensions/EXT_frag_depth/
 @Experimental()
-class ExtFragDepth extends NativeFieldWrapperClass1 {
+class ExtFragDepth extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ExtFragDepth._() { throw new UnsupportedError("Not supported"); }
 
@@ -813,7 +813,7 @@
 @DomName('EXTTextureFilterAnisotropic')
 // http://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
 @Experimental()
-class ExtTextureFilterAnisotropic extends NativeFieldWrapperClass1 {
+class ExtTextureFilterAnisotropic extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ExtTextureFilterAnisotropic._() { throw new UnsupportedError("Not supported"); }
 
@@ -836,7 +836,7 @@
 @DocsEditable()
 @DomName('WebGLFramebuffer')
 @Unstable()
-class Framebuffer extends NativeFieldWrapperClass1 {
+class Framebuffer extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Framebuffer._() { throw new UnsupportedError("Not supported"); }
 
@@ -852,7 +852,7 @@
 @DomName('WebGLLoseContext')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_lose_context/
 @Experimental()
-class LoseContext extends NativeFieldWrapperClass1 {
+class LoseContext extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory LoseContext._() { throw new UnsupportedError("Not supported"); }
 
@@ -876,7 +876,7 @@
 @DomName('OESElementIndexUint')
 // http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/
 @Experimental() // experimental
-class OesElementIndexUint extends NativeFieldWrapperClass1 {
+class OesElementIndexUint extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory OesElementIndexUint._() { throw new UnsupportedError("Not supported"); }
 
@@ -892,7 +892,7 @@
 @DomName('OESStandardDerivatives')
 // http://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
 @Experimental() // experimental
-class OesStandardDerivatives extends NativeFieldWrapperClass1 {
+class OesStandardDerivatives extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory OesStandardDerivatives._() { throw new UnsupportedError("Not supported"); }
 
@@ -912,7 +912,7 @@
 @DomName('OESTextureFloat')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_float/
 @Experimental() // experimental
-class OesTextureFloat extends NativeFieldWrapperClass1 {
+class OesTextureFloat extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory OesTextureFloat._() { throw new UnsupportedError("Not supported"); }
 
@@ -928,7 +928,7 @@
 @DomName('OESTextureFloatLinear')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_float_linear/
 @Experimental()
-class OesTextureFloatLinear extends NativeFieldWrapperClass1 {
+class OesTextureFloatLinear extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory OesTextureFloatLinear._() { throw new UnsupportedError("Not supported"); }
 
@@ -944,7 +944,7 @@
 @DomName('OESTextureHalfFloat')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/
 @Experimental() // experimental
-class OesTextureHalfFloat extends NativeFieldWrapperClass1 {
+class OesTextureHalfFloat extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory OesTextureHalfFloat._() { throw new UnsupportedError("Not supported"); }
 
@@ -964,7 +964,7 @@
 @DomName('OESTextureHalfFloatLinear')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float_linear/
 @Experimental()
-class OesTextureHalfFloatLinear extends NativeFieldWrapperClass1 {
+class OesTextureHalfFloatLinear extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory OesTextureHalfFloatLinear._() { throw new UnsupportedError("Not supported"); }
 
@@ -980,7 +980,7 @@
 @DomName('OESVertexArrayObject')
 // http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
 @Experimental() // experimental
-class OesVertexArrayObject extends NativeFieldWrapperClass1 {
+class OesVertexArrayObject extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory OesVertexArrayObject._() { throw new UnsupportedError("Not supported"); }
 
@@ -1015,7 +1015,7 @@
 @DocsEditable()
 @DomName('WebGLProgram')
 @Unstable()
-class Program extends NativeFieldWrapperClass1 {
+class Program extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Program._() { throw new UnsupportedError("Not supported"); }
 
@@ -1030,7 +1030,7 @@
 @DocsEditable()
 @DomName('WebGLRenderbuffer')
 @Unstable()
-class Renderbuffer extends NativeFieldWrapperClass1 {
+class Renderbuffer extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Renderbuffer._() { throw new UnsupportedError("Not supported"); }
 
@@ -2900,7 +2900,7 @@
 
 @DocsEditable()
 @DomName('WebGLShader')
-class Shader extends NativeFieldWrapperClass1 {
+class Shader extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Shader._() { throw new UnsupportedError("Not supported"); }
 
@@ -2914,7 +2914,7 @@
 
 @DocsEditable()
 @DomName('WebGLShaderPrecisionFormat')
-class ShaderPrecisionFormat extends NativeFieldWrapperClass1 {
+class ShaderPrecisionFormat extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory ShaderPrecisionFormat._() { throw new UnsupportedError("Not supported"); }
 
@@ -2940,7 +2940,7 @@
 
 @DocsEditable()
 @DomName('WebGLTexture')
-class Texture extends NativeFieldWrapperClass1 {
+class Texture extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory Texture._() { throw new UnsupportedError("Not supported"); }
 
@@ -2954,7 +2954,7 @@
 
 @DocsEditable()
 @DomName('WebGLUniformLocation')
-class UniformLocation extends NativeFieldWrapperClass1 {
+class UniformLocation extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory UniformLocation._() { throw new UnsupportedError("Not supported"); }
 
@@ -2970,7 +2970,7 @@
 @DomName('WebGLVertexArrayObjectOES')
 // http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
 @Experimental() // experimental
-class VertexArrayObject extends NativeFieldWrapperClass1 {
+class VertexArrayObject extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory VertexArrayObject._() { 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 435d70b..81f384d 100644
--- a/sdk/lib/web_sql/dartium/web_sql_dartium.dart
+++ b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
@@ -81,7 +81,7 @@
 @Experimental()
 // http://www.w3.org/TR/webdatabase/#asynchronous-database-api
 @Experimental() // deprecated
-class SqlDatabase extends NativeFieldWrapperClass1 {
+class SqlDatabase extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SqlDatabase._() { throw new UnsupportedError("Not supported"); }
 
@@ -128,7 +128,7 @@
 @DomName('SQLError')
 // http://www.w3.org/TR/webdatabase/#sqlerror
 @Experimental() // deprecated
-class SqlError extends NativeFieldWrapperClass1 {
+class SqlError extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SqlError._() { throw new UnsupportedError("Not supported"); }
 
@@ -184,7 +184,7 @@
 @DomName('SQLResultSet')
 // http://www.w3.org/TR/webdatabase/#sqlresultset
 @Experimental() // deprecated
-class SqlResultSet extends NativeFieldWrapperClass1 {
+class SqlResultSet extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SqlResultSet._() { throw new UnsupportedError("Not supported"); }
 
@@ -212,7 +212,7 @@
 @DomName('SQLResultSetRowList')
 // http://www.w3.org/TR/webdatabase/#sqlresultsetrowlist
 @Experimental() // deprecated
-class SqlResultSetRowList extends NativeFieldWrapperClass1 with ListMixin<Map>, ImmutableListMixin<Map> implements List {
+class SqlResultSetRowList extends NativeFieldWrapperClass2 with ListMixin<Map>, ImmutableListMixin<Map> implements List {
   // To suppress missing implicit constructor warnings.
   factory SqlResultSetRowList._() { throw new UnsupportedError("Not supported"); }
 
@@ -284,7 +284,7 @@
 @Experimental()
 // http://www.w3.org/TR/webdatabase/#sqltransaction
 @deprecated // deprecated
-class SqlTransaction extends NativeFieldWrapperClass1 {
+class SqlTransaction extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory SqlTransaction._() { throw new UnsupportedError("Not supported"); }
 
@@ -307,7 +307,7 @@
 @Experimental()
 // http://www.w3.org/TR/webdatabase/#sqltransactionsync
 @Experimental() // deprecated
-abstract class _SQLTransactionSync extends NativeFieldWrapperClass1 {
+abstract class _SQLTransactionSync extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
   factory _SQLTransactionSync._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 5c7b8ac..3ca6991 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -16,12 +16,6 @@
 Language/15_Types/4_Interface_Types_A11_t01: Skip
 Language/15_Types/4_Interface_Types_A11_t02: Skip
 
-# TBF: "class B1 = A with M1;", typedef cannot be used for mixins
-Language/09_Mixins/1_Mixin_Application_A01_t01: Fail
-
-# TBF: It is a compile-time error if the key of an entry in a constant map literal is an instance of a class that implements the operator == unless the key is a string or integer.
-Language/12_Expressions/07_Maps_A13_t01: Fail
-
 # TBF: malformed or malbounded type in "conts" is static warning
 Language/12_Expressions/12_Instance_Creation_A01_t08: Fail
 
@@ -163,21 +157,12 @@
 LibTest/async/StreamEventTransformer/handleDone_A01_t01: Fail
 LibTest/async/StreamEventTransformer/handleError_A01_t01: Fail
 
-Language/07_Classes/07_Classes_A13_t01: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t02: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t03: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t04: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t05: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t06: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t07: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t08: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t09: Fail # co19-roll r623: Please triage this failure
+Language/13_Statements/09_Switch_A02_t04: Fail  # Issue 629
+
 Language/07_Classes/6_Constructors/2_Factories_A14_t01: Fail # co19-roll r623: Please triage this failure
 Language/07_Classes/6_Constructors/2_Factories_A14_t02: Fail # co19-roll r623: Please triage this failure
-Language/12_Expressions/01_Constants_A16_t02: Crash # co19-roll r623: Please triage this failure
 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
-
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 26daf58..11c10df 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -16,8 +16,6 @@
 Language/05_Variables/05_Variables_A06_t04: fail, pass, ok # co19 issue 624
 Language/05_Variables/05_Variables_A06_t05: fail, pass, ok # co19 issue 624
 Language/05_Variables/05_Variables_A06_t06: fail, pass, ok # co19 issue 624
-Language/12_Expressions/05_Strings_A02_t46: fail, pass, ok # co19 issue 612
-Language/12_Expressions/05_Strings_A02_t48: fail, pass, ok # co19 issue 612
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail # co19-roll r587: Please triage this failure
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail # co19-roll r587: Please triage this failure
 LibTest/core/Uri/toFilePath_A01_t01: pass, fail, ok # co19 Issue 592
@@ -27,21 +25,13 @@
 
 Language/12_Expressions/18_Assignment_A04_t09: RuntimeError # co19-roll r607: Please triage this failure
 Language/13_Statements/04_Local_Function_Declaration_A04_t01: MissingCompileTimeError # co19-roll r607: Please triage this failure
-Language/13_Statements/02_Expression_Statements_A01_t13: MissingCompileTimeError # co19-roll r607: Please triage this failure
-LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/collection/LinkedList/forEach_A02_t01: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/Symbol/Symbol_A01_t04: RuntimeError # co19-roll r607: Please triage this failure
 
-Language/07_Classes/07_Classes_A13_t01: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t02: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t03: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t04: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t05: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t06: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t07: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t08: MissingCompileTimeError # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t09: MissingCompileTimeError # co19-roll r623: Please triage this failure
+Language/07_Classes/07_Classes_A13_t01: Pass, MissingCompileTimeError # co19-roll r623: Please triage this failure
+Language/07_Classes/07_Classes_A13_t04: Pass, MissingCompileTimeError # co19-roll r623: Please triage this failure
+Language/07_Classes/07_Classes_A13_t07: Pass, MissingCompileTimeError # co19-roll r623: Please triage this failure
 Language/07_Classes/6_Constructors/2_Factories_A14_t01: MissingCompileTimeError # co19-roll r623: Please triage this failure
 Language/07_Classes/6_Constructors/2_Factories_A14_t02: MissingCompileTimeError # co19-roll r623: Please triage this failure
 LibTest/collection/HashSet/HashSet_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 21e414b..2c64a3f 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -3,6 +3,13 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2dart ]
+Language/07_Classes/07_Classes_A13_t02: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t03: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t05: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t06: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t08: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t09: Fail # Missing CT error on member with same name a type parameter
+
 LibTest/async/Stream/Stream.periodic_A01_t01: Pass, Fail # Issue 12562.
 LibTest/core/Symbol/Symbol_A01_t02: CompileTimeError # co19-roll r607: Please triage this failure
 
@@ -35,7 +42,6 @@
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: Fail # Issue 13652
 Language/07_Classes/6_Constructors_A02_t01: Fail # http://dartbug.com/5519
 Language/12_Expressions/01_Constants_A03_t01: Fail # Issue 13652
-Language/13_Statements/09_Switch_A02_t04: Fail # co19 issue 605
 
 LibTest/core/Match/operator_subscript_A01_t01: Fail # inherited from VM
 LibTest/core/Match/operator_subscript_A01_t01: Fail, OK # co19 issue 294
@@ -79,7 +85,6 @@
 LibTest/math/atan_A01_t01: Fail, OK # co19 issue 44
 
 [ $compiler == dart2dart ]
-Language/13_Statements/09_Switch_A02_t04: CompileTimeError, OK # co19 issue 628
 Language/03_Overview/2_Privacy_A01_t06: Fail # co19 issue 463
 LibTest/core/double/ceil_A01_t03: Fail # truncate/ceil/floor/round returns ints, issue 389
 LibTest/core/double/ceil_A01_t04: Fail # truncate/ceil/floor/round returns ints, issue 389
@@ -88,7 +93,6 @@
 LibTest/core/double/round_A01_t02: Fail # truncate/ceil/floor/round returns ints, issue 389
 LibTest/core/double/round_A01_t04: Fail # truncate/ceil/floor/round returns ints, issue 389
 
-Language/14_Libraries_and_Scripts/1_Imports_A01_t17: Fail # co19 Issue 603
 Language/14_Libraries_and_Scripts/1_Imports_A04_t01: Fail # co19 Issue 603
 
 
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index cddecd2..ed14cd3 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -15,6 +15,12 @@
 # Crashes first, please. Then untriaged bugs. There is a section below
 # for co19 bugs.
 [ $compiler == dart2js ]
+Language/07_Classes/07_Classes_A13_t02: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t03: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t05: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t06: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t08: Fail # Missing CT error on member with same name a type parameter
+Language/07_Classes/07_Classes_A13_t09: Fail # Missing CT error on member with same name a type parameter
 Language/03_Overview/1_Scoping_A02_t05: CompileTimeError # TODO(ahe): Please triage this failure.
 Language/03_Overview/1_Scoping_A02_t06: CompileTimeError # TODO(ahe): Please triage this failure.
 Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: fail # co19-roll r576: Please triage this failure
@@ -160,7 +166,6 @@
 # can understand so he can file a bug later.
 #
 [ $compiler == dart2js ]
-Language/13_Statements/09_Switch_A02_t04: CompileTimeError, OK # co19 issue 628
 Language/03_Overview/2_Privacy_A01_t09: RuntimeError, OK # co19 issue 198
 Language/03_Overview/2_Privacy_A01_t11: Pass, OK # co19 issue 316
 Language/06_Functions/4_External_Functions_A01_t01: CompileTimeError, OK # http://dartbug.com/5021
@@ -227,7 +232,6 @@
 LibTest/typed_data/ByteData/setUint8_A02_t02: fail # Issue 12989
 LibTest/typed_data/ByteData/setUint8_A02_t02: fail # Issue 12989
 
-Language/14_Libraries_and_Scripts/1_Imports_A01_t17: Fail # co19 Issue 603
 Language/14_Libraries_and_Scripts/1_Imports_A04_t01: Fail # co19 Issue 603
 
 [ $compiler == dart2js && $jscl ]
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index 5f35f36..87bc8a6 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -18,14 +18,8 @@
 Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Issue 13719: Please triage this failure.
 Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Issue 13719: Please triage this failure.
 Language/07_Classes/07_Classes_A13_t01: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t02: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t03: Fail # co19-roll r623: Please triage this failure
 Language/07_Classes/07_Classes_A13_t04: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t05: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t06: Fail # co19-roll r623: Please triage this failure
 Language/07_Classes/07_Classes_A13_t07: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t08: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/07_Classes_A13_t09: Fail # co19-roll r623: Please triage this failure
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: Pass, Fail # Issue 13719: Please triage this failure.
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: Fail # Issue 13719: Please triage this failure.
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: Fail # Issue 13719: Please triage this failure.
@@ -33,15 +27,11 @@
 Language/07_Classes/6_Constructors/2_Factories_A14_t02: Fail # co19-roll r623: Please triage this failure
 Language/12_Expressions/01_Constants_A16_t04: Fail # Issue 13719: Please triage this failure.
 Language/12_Expressions/01_Constants_A16_t05: Fail # Issue 13719: Please triage this failure.
-Language/12_Expressions/05_Strings_A02_t46: Fail # Issue 13719: Please triage this failure.
-Language/12_Expressions/05_Strings_A02_t48: Fail # Issue 13719: Please triage this failure.
 Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: Fail # Issue 13719: Please triage this failure.
 Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: Fail # Issue 13719: Please triage this failure.
 Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: Fail # Issue 13719: Please triage this failure.
-Language/12_Expressions/18_Assignment_A01_t07: Fail  # co19-roll r607: Please triage this failure
 Language/12_Expressions/18_Assignment_A04_t09: Fail # co19-roll r607: Please triage this failure
 Language/12_Expressions/30_Identifier_Reference_A08_t02: Fail # Issue 13719: Please triage this failure.
-Language/13_Statements/02_Expression_Statements_A01_t13: Fail # co19-roll r607: Please triage this failure
 Language/13_Statements/03_Variable_Declaration_A04_t01: Fail # co19-roll r607: Please triage this failure
 Language/13_Statements/03_Variable_Declaration_A04_t02: Fail # co19-roll r607: Please triage this failure
 Language/13_Statements/03_Variable_Declaration_A04_t05: Fail # co19-roll r607: Please triage this failure
@@ -51,7 +41,6 @@
 Language/13_Statements/04_Local_Function_Declaration_A04_t01: Fail # co19-roll r607: Please triage this failure
 Language/13_Statements/06_For_A01_t11: Fail # Issue 13719: Please triage this failure.
 Language/13_Statements/09_Switch_A01_t02: Fail # Issue 13719: Please triage this failure.
-Language/13_Statements/09_Switch_A02_t04: Fail # Issue 13719: Please triage this failure.
 Language/13_Statements/12_Labels_A01_t03: Fail # Issue 13719: Please triage this failure.
 Language/14_Libraries_and_Scripts/2_Exports_A04_t02: Fail # Issue 13719: Please triage this failure.
 Language/14_Libraries_and_Scripts/2_Exports_A04_t03: Fail # Issue 13719: Please triage this failure.
@@ -68,7 +57,6 @@
 LibTest/async/Completer/completeError_A02_t01: Pass, Fail # Issue 13719: Please triage this failure.
 LibTest/async/Stream/Stream.periodic_A01_t01: Timeout # Issue 13719: Please triage this failure.
 LibTest/collection/HashSet/HashSet_class_A01_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: Fail # co19-roll r607: Please triage this failure
 LibTest/collection/IterableBase/IterableBase_class_A01_t02: Fail # co19-roll r623: Please triage this failure
 LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: Fail # co19-roll r607: Please triage this failure
 LibTest/collection/LinkedList/forEach_A02_t01: Fail # co19-roll r607: Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 4976130..06df489 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -10,7 +10,6 @@
 Language/13_Statements/03_Variable_Declaration_A04_t05: MissingCompileTimeError # Issue 7052
 Language/13_Statements/03_Variable_Declaration_A04_t06: MissingCompileTimeError # Issue 7052
 
-[ $compiler == none && $runtime == vm ]
 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
 
@@ -31,6 +30,51 @@
 
 LibTest/async/Timer/Timer.periodic_A02_t01: Pass, Fail # co19 issue 537
 
+Language/05_Variables/05_Variables_A05_t01: fail # Dart issue 12539
+Language/05_Variables/05_Variables_A05_t02: fail # Dart issue 12539
+Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: fail # Dart issue 12549
+Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: fail # Dart issue 1372
+Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: fail # co19 issue 525
+Language/12_Expressions/30_Identifier_Reference_A08_t02: fail # Dart issue 12593
+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/13_Statements/06_For_A01_t11: fail # Dart issue 5675
+Language/13_Statements/09_Switch_A01_t02: fail # Dart issue 12908
+Language/13_Statements/12_Labels_A01_t03: fail # Dart issue 2238
+Language/14_Libraries_and_Scripts/2_Exports_A04_t02: fail # Dart issue 12916
+Language/14_Libraries_and_Scripts/2_Exports_A04_t03: fail # Dart issue 12916
+Language/14_Libraries_and_Scripts/4_Scripts_A03_t03: MissingRuntimeError, OK # co19 issue
+Language/14_Libraries_and_Scripts/5_URIs_A01_t04: fail # Issue 12521
+Language/14_Libraries_and_Scripts/5_URIs_A01_t05: fail # Issue 12521
+Language/14_Libraries_and_Scripts/5_URIs_A01_t14: fail # Issue 12521
+Language/14_Libraries_and_Scripts/5_URIs_A01_t15: fail # Issue 12521
+
+LibTest/core/DateTime/parse_A03_t01: fail # Issue 12514
+
+# All isolate are being ignored at the moment as the library will go through some changes.
+LibTest/isolate/IsolateSink/addError_A01_t01: fail # co19-roll r546: Please triage this failure
+LibTest/isolate/IsolateSink/addError_A01_t02: fail # co19-roll r546: Please triage this failure
+LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure
+LibTest/isolate/IsolateStream/contains_A02_t01: fail, pass # co19-roll r546: Please triage this failure
+LibTest/isolate/SendPort/send_A01_t01: fail # co19-roll r546: Please triage this failure
+LibTest/isolate/ReceivePort/receive_A01_t02: Fail # VM triage, check spec.
+LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail # VM triage, check spec.
+LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail # VM triage, check spec.
+
+Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail # co19-roll r587: Please triage this failure
+Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail # co19-roll r587: Please triage this failure
+
+LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # Issue 13543
+LibTest/typed_data/Float32x4/clamp_A02_t01: Pass, Fail # Issue 13543
+LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13543
+LibTest/typed_data/Float32x4/reciprocal_A01_t01: Pass, Fail # Issue 13543
+Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: MissingCompileTimeError # co19-roll r607: Please triage this failure
+Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: MissingCompileTimeError # 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
+
 
 [ $compiler == none && $runtime == vm && $checked ]
 LibTest/async/Future/catchError_A01_t01: Fail # Future constructors have changed # issue 408
@@ -58,41 +102,6 @@
 [ $compiler == none && $runtime == vm && ($arch == simarm || $arch == simmips) ]
 LibTest/core/Uri/Uri_A06_t03: Pass, Timeout # co19-roll r576: Please triage this failure
 
-[ $compiler == none && $runtime == vm ]
-Language/05_Variables/05_Variables_A05_t01: fail # Dart issue 12539
-Language/05_Variables/05_Variables_A05_t02: fail # Dart issue 12539
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: fail # Dart issue 12549
-Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: fail # Dart issue 1372
-Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: fail # co19 issue 525
-Language/12_Expressions/30_Identifier_Reference_A08_t02: fail # Dart issue 12593
-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/13_Statements/06_For_A01_t11: fail # Dart issue 5675
-Language/13_Statements/09_Switch_A02_t04: fail # co19 issue 605
-Language/13_Statements/09_Switch_A01_t02: fail # Dart issue 12908
-Language/13_Statements/12_Labels_A01_t03: fail # Dart issue 2238
-Language/14_Libraries_and_Scripts/2_Exports_A04_t02: fail # Dart issue 12916
-Language/14_Libraries_and_Scripts/2_Exports_A04_t03: fail # Dart issue 12916
-Language/14_Libraries_and_Scripts/5_URIs_A01_t04: fail # Issue 12521
-Language/14_Libraries_and_Scripts/5_URIs_A01_t05: fail # Issue 12521
-Language/14_Libraries_and_Scripts/5_URIs_A01_t14: fail # Issue 12521
-Language/14_Libraries_and_Scripts/5_URIs_A01_t15: fail # Issue 12521
-
-LibTest/core/DateTime/parse_A03_t01: fail # Issue 12514
-
-# All isolate are being ignored at the moment as the library will go through some changes.
-LibTest/isolate/IsolateSink/addError_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateSink/addError_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateStream/contains_A02_t01: fail, pass # co19-roll r546: Please triage this failure
-LibTest/isolate/SendPort/send_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/ReceivePort/receive_A01_t02: Fail # VM triage, check spec.
-LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail # VM triage, check spec.
-LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail # VM triage, check spec.
-
-Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail # co19-roll r587: Please triage this failure
-Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail # co19-roll r587: Please triage this failure
-
 [ $compiler == none && $runtime == vm && $checked ]
 LibTest/typed_data/Float32x4List/elementAt_A01_t01: Fail # Dart issue 12861
 LibTest/typed_data/Float32x4List/fillRange_A01_t01: Fail # Dart issue 12861
@@ -121,17 +130,5 @@
 Language/15_Types/4_Interface_Types_A11_t01: pass, timeout # Issue 13349
 Language/15_Types/4_Interface_Types_A11_t02: pass, timeout # Issue 13349
 
-[ $compiler == none && $runtime == vm ]
-LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # Issue 13543
-LibTest/typed_data/Float32x4/clamp_A02_t01: Pass, Fail # Issue 13543
-LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13543
-LibTest/typed_data/Float32x4/reciprocal_A01_t01: Pass, Fail # Issue 13543
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: MissingCompileTimeError # co19-roll r607: Please triage this failure
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: MissingCompileTimeError # 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
-
 [ $compiler == none && $runtime == vm && $unchecked ]
 LibTest/core/List/List_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
diff --git a/tests/compiler/dart2js/analyze_helper.dart b/tests/compiler/dart2js/analyze_helper.dart
index 3eee5f8..affcf0d 100644
--- a/tests/compiler/dart2js/analyze_helper.dart
+++ b/tests/compiler/dart2js/analyze_helper.dart
@@ -125,7 +125,7 @@
 
 Future analyze(List<Uri> uriList, Map<String, List<String>> whiteList) {
   var libraryRoot = currentDirectory.resolve('sdk/');
-  var provider = new SourceFileProvider();
+  var provider = new CompilerSourceFileProvider();
   var handler = new CollectingDiagnosticHandler(whiteList, provider);
   var compiler = new Compiler(
       provider.readStringFromUri,
diff --git a/tests/compiler/dart2js/begin_end_token_test.dart b/tests/compiler/dart2js/begin_end_token_test.dart
index fe8c910..34d18a6 100644
--- a/tests/compiler/dart2js/begin_end_token_test.dart
+++ b/tests/compiler/dart2js/begin_end_token_test.dart
@@ -16,7 +16,7 @@
   Expect.isNotNull(endToken, debug);
 
   int begin = beginToken.charOffset;
-  int end = endToken.charOffset + endToken.slowCharCount;
+  int end = endToken.charOffset + endToken.charCount;
   Expect.isTrue(begin <= end, debug);
 
   if (hard) {
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index 541face..04e6b13 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -20,7 +20,7 @@
   compiler.disableInlining = disableInlining;
   asyncTest(() => compiler.runCompiler(uri).then((_) {
     var cls = findElement(compiler, className);
-    var member = cls.lookupLocalMember(buildSourceString(memberName));
+    var member = cls.lookupLocalMember(memberName);
     return check(compiler, member);
   }));
 }
diff --git a/tests/compiler/dart2js/codegen_helper.dart b/tests/compiler/dart2js/codegen_helper.dart
index 1993ec5..eea5d58 100644
--- a/tests/compiler/dart2js/codegen_helper.dart
+++ b/tests/compiler/dart2js/codegen_helper.dart
@@ -6,8 +6,6 @@
 import 'package:expect/expect.dart';
 
 import 'memory_source_file_helper.dart';
-import "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart"
-    show SourceString;
 
 Future<Map<String, String>> generate(String code,
     [List<String> options = const []]) {
@@ -30,7 +28,7 @@
     Map<String, String> result = new Map<String, String>();
     for (var element in compiler.backend.generatedCode.keys) {
       if (element.getCompilationUnit().script.uri != uri) continue;
-      var name = element.name.slowToString();
+      var name = element.name;
       var code = compiler.backend.assembleCode(element);
       result[name] = code;
     }
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index 3e76675..64ef727 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -62,7 +62,7 @@
                        interceptorsSource: interceptorsSource,
                        enableMinification: minify);
   compiler.parseScript(code);
-  lego.Element element = compiler.mainApp.find(buildSourceString(entry));
+  lego.Element element = compiler.mainApp.find(entry);
   if (element == null) return null;
   compiler.phase = Compiler.PHASE_RESOLVING;
   compiler.backend.enqueueHelpers(compiler.enqueuer.resolution,
@@ -89,7 +89,8 @@
       analyzeAll: analyzeAll,
       analyzeOnly: analyzeOnly,
       coreSource: coreSource);
-  compiler.sourceFiles[uri.toString()] = new SourceFile(uri.toString(), code);
+  compiler.sourceFiles[uri.toString()] =
+      new StringSourceFile(uri.toString(), code);
   return compiler;
 }
 
@@ -132,14 +133,14 @@
 }
 
 lego.Element findElement(compiler, String name) {
-  var element = compiler.mainApp.find(buildSourceString(name));
+  var element = compiler.mainApp.find(name);
   Expect.isNotNull(element, 'Could not locate $name.');
   return element;
 }
 
 types.TypeMask findTypeMask(compiler, String name,
                             [String how = 'nonNullExact']) {
-  var sourceName = buildSourceString(name);
+  var sourceName = name;
   var element = compiler.mainApp.find(sourceName);
   if (element == null) {
     element = compiler.interceptorsLibrary.find(sourceName);
diff --git a/tests/compiler/dart2js/compiler_test.dart b/tests/compiler/dart2js/compiler_test.dart
index 83902ad..0b2631c 100644
--- a/tests/compiler/dart2js/compiler_test.dart
+++ b/tests/compiler/dart2js/compiler_test.dart
@@ -39,7 +39,7 @@
   CallbackMockCompiler compiler = new CallbackMockCompiler();
   ResolverVisitor visitor = compiler.resolverVisitor();
   compiler.parseScript('NoSuchPrefix.NoSuchType foo() {}');
-  FunctionElement foo = compiler.mainApp.find(buildSourceString('foo'));
+  FunctionElement foo = compiler.mainApp.find('foo');
   compiler.setOnWarning(
       (c, n, m) => Expect.equals(foo, compiler.currentElement));
   foo.computeType(compiler);
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index 044d9f3..32a90c5 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -24,7 +24,7 @@
 
   visitSend(Send node) {
     if (node.isPropertyAccess
-        && node.selector.asIdentifier().source.slowToString() == identifier) {
+        && node.selector.asIdentifier().source == identifier) {
       result = node;
     } else {
       node.visitChildren(this);
@@ -64,12 +64,12 @@
     map = inferrer.baseTypes.mapBaseType;
     nullType = const NullBaseType();
     functionType = inferrer.baseTypes.functionBaseType;
-    Element mainElement = compiler.mainApp.find(buildSourceString('main'));
+    Element mainElement = compiler.mainApp.find('main');
     ast = mainElement.parseNode(compiler);
   }
 
   BaseType base(String className) {
-    final source = buildSourceString(className);
+    final source = className;
     return new ClassBaseType(compiler.mainApp.find(source));
   }
 
@@ -89,8 +89,8 @@
    * Finds the [Element] corresponding to [: className#fieldName :].
    */
   Element findField(String className, String fieldName) {
-    ClassElement element = compiler.mainApp.find(buildSourceString(className));
-    return element.lookupLocalMember(buildSourceString(fieldName));
+    ClassElement element = compiler.mainApp.find(className);
+    return element.lookupLocalMember(fieldName);
   }
 
   ConcreteType concreteFrom(List<BaseType> baseTypes) {
@@ -182,7 +182,8 @@
       coreSource: CORELIB,
       enableConcreteTypeInference: true,
       maxConcreteTypeSize: maxConcreteTypeSize);
-  compiler.sourceFiles[uri.toString()] = new SourceFile(uri.toString(), code);
+  compiler.sourceFiles[uri.toString()] =
+      new StringSourceFile(uri.toString(), code);
   compiler.typesTask.concreteTypesInferrer.testMode = true;
   return compiler.runCompiler(uri).then((_) {
     return new AnalysisResult(compiler);
@@ -1541,7 +1542,7 @@
     ClassElement y = findElement(result.compiler, 'Y');
     ClassElement z = findElement(result.compiler, 'Z');
 
-    Selector foo = new Selector.call(buildSourceString("foo"), null, 0);
+    Selector foo = new Selector.call("foo", null, 0);
 
     Expect.equals(
         inferredType(foo).simplify(result.compiler),
@@ -1560,7 +1561,7 @@
             xy, foo)).simplify(result.compiler),
         new TypeMask.nonNullSubclass(bc));
 
-    Selector bar = new Selector.call(buildSourceString("bar"), null, 0);
+    Selector bar = new Selector.call("bar", null, 0);
 
     Expect.isNull(inferredType(bar));
   });
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index 2ffcc04..4ff8edd 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -36,12 +36,9 @@
         compiler.deferredLoadTask.allDeferredElements.where((e) => e.isClass())
         .toSet();
 
-    var dateTime =
-        deferredClasses
-            .where((e) => e.name.slowToString() == 'DateTime').single;
+    var dateTime = deferredClasses.where((e) => e.name == 'DateTime').single;
 
-    var myClass =
-        deferredClasses.where((e) => e.name.slowToString() == 'MyClass').single;
+    var myClass = deferredClasses.where((e) => e.name == 'MyClass').single;
 
     var deferredLibrary = compiler.libraries['memory:deferred.dart'];
 
diff --git a/tests/compiler/dart2js/erroneous_element_test.dart b/tests/compiler/dart2js/erroneous_element_test.dart
index 4a588e1..893dc3c 100644
--- a/tests/compiler/dart2js/erroneous_element_test.dart
+++ b/tests/compiler/dart2js/erroneous_element_test.dart
@@ -15,6 +15,6 @@
 void main() {
   ErroneousElement e = new ErroneousElementX(MessageKind.GENERIC,
                                              {'text': 'error'},
-                                             buildSourceString('foo'), null);
+                                             'foo', null);
   Expect.stringEquals('<foo: error>', '$e');
 }
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 7961fe6..1356bc11 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -21,7 +21,7 @@
   asyncTest(() => compiler.runCompiler(uri).then((_) {
     compiler.disableInlining = disableInlining;
     var cls = findElement(compiler, className);
-    var member = cls.lookupMember(buildSourceString(memberName));
+    var member = cls.lookupMember(memberName);
     check(compiler, member);
   }));
 }
diff --git a/tests/compiler/dart2js/find_my_name_test.dart b/tests/compiler/dart2js/find_my_name_test.dart
index dc24326..72f42fc 100644
--- a/tests/compiler/dart2js/find_my_name_test.dart
+++ b/tests/compiler/dart2js/find_my_name_test.dart
@@ -35,7 +35,7 @@
   ClassElement cls = parseUnit(code, compiler, compiler.mainApp).head;
   cls.parseNode(compiler);
   for (Element e in cls.localMembers) {
-    String name = e.name.slowToString();
+    String name = e.name;
     if (e.isConstructor()) {
       name = Elements.reconstructConstructorName(e).replaceFirst(r'$', '.');
     }
diff --git a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
index 2c27c74..afa0af3 100644
--- a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
@@ -32,7 +32,7 @@
     checkNumberOfMatches(matches, 1);
     var cls = findElement(compiler, 'A');
     Expect.isNotNull(cls);
-    SourceString name = buildSourceString('foo');
+    String name = 'foo';
     var element = cls.lookupLocalMember(name);
     Expect.isNotNull(element);
     Selector selector = new Selector.getter(name, null);
diff --git a/tests/compiler/dart2js/issue13354_test.dart b/tests/compiler/dart2js/issue13354_test.dart
index 8ca8614..d9342b6 100644
--- a/tests/compiler/dart2js/issue13354_test.dart
+++ b/tests/compiler/dart2js/issue13354_test.dart
@@ -42,7 +42,7 @@
 
     checkReturnInClass(String className, String methodName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(methodName));
+      var element = cls.lookupLocalMember(methodName);
       Expect.equals(type,
           typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
     }
diff --git a/tests/compiler/dart2js/lookup_member_test.dart b/tests/compiler/dart2js/lookup_member_test.dart
index 261e53c..f87b672 100644
--- a/tests/compiler/dart2js/lookup_member_test.dart
+++ b/tests/compiler/dart2js/lookup_member_test.dart
@@ -32,7 +32,7 @@
       """).then((env) {
     void expect(DartType receiverType, String memberName,
                 DartType expectedType) {
-      Member member = receiverType.lookupMember(env.sourceString(memberName));
+      Member member = receiverType.lookupMember(memberName);
       Expect.isNotNull(member);
       DartType memberType = member.computeType(env.compiler);
       Expect.equals(expectedType, memberType,
diff --git a/tests/compiler/dart2js/memory_source_file_helper.dart b/tests/compiler/dart2js/memory_source_file_helper.dart
index 135b025..c2e14e1 100644
--- a/tests/compiler/dart2js/memory_source_file_helper.dart
+++ b/tests/compiler/dart2js/memory_source_file_helper.dart
@@ -15,7 +15,7 @@
        show currentDirectory, nativeToUriPath;
 
 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart'
-       show SourceFile;
+       show StringSourceFile;
 
 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart'
        show SourceFileProvider;
@@ -37,7 +37,9 @@
       return new Future.error(new Exception('No such file $resourceUri'));
     }
     String resourceName = '$resourceUri';
-    this.sourceFiles[resourceName] = new SourceFile(resourceName, source);
+    this.sourceFiles[resourceName] = new StringSourceFile(resourceName, source);
     return new Future.value(source);
   }
+
+  Future<String> call(Uri resourceUri) => readStringFromUri(resourceUri);
 }
diff --git a/tests/compiler/dart2js/message_kind_helper.dart b/tests/compiler/dart2js/message_kind_helper.dart
index 4c513ea..b8a8fd5 100644
--- a/tests/compiler/dart2js/message_kind_helper.dart
+++ b/tests/compiler/dart2js/message_kind_helper.dart
@@ -61,6 +61,7 @@
         }
       }
       Expect.isTrue(messageFound, '"$pattern" does not match any in $messages');
+      Expect.isFalse(compiler.hasCrashed);
       cachedCompiler = compiler;
     });
   }).then((_) => cachedCompiler);
diff --git a/tests/compiler/dart2js/metadata_test.dart b/tests/compiler/dart2js/metadata_test.dart
index 3f84263..f1bc8da 100644
--- a/tests/compiler/dart2js/metadata_test.dart
+++ b/tests/compiler/dart2js/metadata_test.dart
@@ -82,7 +82,7 @@
     Expect.equals(0, length(element.metadata));
     element.ensureResolved(compiler);
     Expect.equals(0, length(element.metadata));
-    element = element.lookupLocalMember(buildSourceString(name));
+    element = element.lookupLocalMember(name);
     Expect.equals(1, length(element.metadata));
     PartialMetadataAnnotation annotation = element.metadata.head;
     annotation.ensureResolved(compiler);
@@ -106,7 +106,7 @@
     Expect.equals(0, length(element.metadata));
     element.ensureResolved(compiler);
     Expect.equals(0, length(element.metadata));
-    element = element.lookupLocalMember(buildSourceString(name));
+    element = element.lookupLocalMember(name);
     Expect.equals(2, length(element.metadata));
     PartialMetadataAnnotation annotation1 = element.metadata.head;
     PartialMetadataAnnotation annotation2 = element.metadata.tail.head;
diff --git a/tests/compiler/dart2js/mini_parser_test.dart b/tests/compiler/dart2js/mini_parser_test.dart
deleted file mode 100644
index dc2d642..0000000
--- a/tests/compiler/dart2js/mini_parser_test.dart
+++ /dev/null
@@ -1,20 +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.
-
-// Simple test to ensure that mini_parser keeps working.
-
-import 'dart:io';
-import '../../../sdk/lib/_internal/compiler/implementation/tools/mini_parser.dart'
-    as tool;
-
-void main() {
-  // Parse this script itself.
-  tool.toolMain(<String>[ Platform.script ]);
-}
-
-/** This class is unused but used to test mini_parser.dart. */
-class TestClass {
-  foo() {}
-  var i;
-}
diff --git a/tests/compiler/dart2js/mirror_helper_rename_test.dart b/tests/compiler/dart2js/mirror_helper_rename_test.dart
index 9b82355..10a1e22 100644
--- a/tests/compiler/dart2js/mirror_helper_rename_test.dart
+++ b/tests/compiler/dart2js/mirror_helper_rename_test.dart
@@ -16,10 +16,6 @@
     '../../../sdk/lib/_internal/compiler/implementation/dart_backend/dart_backend.dart';
 import
     '../../../sdk/lib/_internal/compiler/implementation/mirror_renamer/mirror_renamer.dart';
-import
-    '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart'
-show
-    SourceString;
 
 main() {
   testWithMirrorHelperLibrary(minify: true);
@@ -46,7 +42,7 @@
     DartBackend backend = compiler.backend;
     MirrorRenamer mirrorRenamer = backend.mirrorRenamer;
     Map<Node, String> renames = backend.renames;
-    Map<String, SourceString> symbols = mirrorRenamer.symbols;
+    Map<String, String> symbols = mirrorRenamer.symbols;
 
     Expect.isFalse(null == backend.mirrorHelperLibrary);
     Expect.isFalse(null == backend.mirrorHelperGetNameFunction);
@@ -55,10 +51,10 @@
       if (symbols.containsKey(renames[n])) {
         if(n.toString() == 'getName') {
           Expect.equals(
-              const SourceString(MirrorRenamer.MIRROR_HELPER_GET_NAME_FUNCTION),
+              MirrorRenamer.MIRROR_HELPER_GET_NAME_FUNCTION,
               symbols[renames[n]]);
         } else {
-          Expect.equals(n.toString(), symbols[renames[n]].stringValue);
+          Expect.equals(n.toString(), symbols[renames[n]]);
         }
       }
     }
@@ -74,7 +70,7 @@
       Expect.equals(2, i.length);
     }
 
-    String mapMatch = 'const<String,SourceString>';
+    String mapMatch = 'const<String,String>';
     i = mapMatch.allMatches(output);
     Expect.equals(1, i.length);
   }));
diff --git a/tests/compiler/dart2js/mirror_helper_test.dart b/tests/compiler/dart2js/mirror_helper_test.dart
index b2f2b29..57c869b 100644
--- a/tests/compiler/dart2js/mirror_helper_test.dart
+++ b/tests/compiler/dart2js/mirror_helper_test.dart
@@ -24,10 +24,6 @@
     '../../../sdk/lib/_internal/compiler/implementation/mirror_renamer/mirror_renamer.dart'
 show
     MirrorRenamer;
-import
-    '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart'
-show
-    SourceString;
 
 
 main() {
diff --git a/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart b/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart
index 490aad3..fd0c83f 100644
--- a/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart
+++ b/tests/compiler/dart2js/mirror_helper_unique_minification_test.dart
@@ -40,7 +40,7 @@
     DartBackend backend = compiler.backend;
     MirrorRenamer mirrorRenamer = backend.mirrorRenamer;
     Map<Node, String> renames = backend.renames;
-    Map<String, SourceString> symbols = mirrorRenamer.symbols;
+    Map<String, String> symbols = mirrorRenamer.symbols;
 
     // Check that no two different source code names get the same mangled name,
     // with the exception of MirrorSystem.getName that gets renamed to the same
@@ -48,7 +48,7 @@
     for (Node node in renames.keys) {
       Identifier identifier = node.asIdentifier();
       if (identifier != null) {
-        SourceString source = identifier.source;
+        String source = identifier.source;
         if (mirrorRenamer.mirrorSystemGetNameNodes.first.selector == node)
           continue;
         if (symbols.containsKey(renames[node])) {
diff --git a/tests/compiler/dart2js/mirrors_test.dart b/tests/compiler/dart2js/mirrors_test.dart
index 0d6119b..f8b5580 100644
--- a/tests/compiler/dart2js/mirrors_test.dart
+++ b/tests/compiler/dart2js/mirrors_test.dart
@@ -46,7 +46,7 @@
       currentDirectory.resolve(nativeToUriPath(Platform.script));
   Uri libUri = scriptUri.resolve('../../../sdk/');
   Uri inputUri = scriptUri.resolve('mirrors_helper.dart');
-  var provider = new SourceFileProvider();
+  var provider = new CompilerSourceFileProvider();
   var diagnosticHandler =
         new FormattingDiagnosticHandler(provider).diagnosticHandler;
   asyncStart();
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 3dd0e0a..eed4542 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -17,7 +17,6 @@
 
 import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart' show
     Constant,
-    SourceString,
     TypeConstant;
 
 import
@@ -80,8 +79,7 @@
 
     for (var library in compiler.libraries.values) {
       library.forEachLocalMember((member) {
-        if (library == compiler.mainApp
-            && member.name == const SourceString('Foo')) {
+        if (library == compiler.mainApp && member.name == 'Foo') {
           Expect.isTrue(
               compiler.backend.isNeededForReflection(member), '$member');
           member.forEachLocalMember((classMember) {
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 73eea5c..4c497d3 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -82,7 +82,6 @@
                        String contextName, var context,
                        var typeArguments) {}
   computeSignature(var signature, var context, var contextName) {}
-  defineNativeMethodsFinish() {}
   getRuntimeTypeArguments(target, substitutionName) {}
   voidTypeCheck(value) {}''';
 
@@ -211,6 +210,8 @@
   api.DiagnosticHandler diagnosticHandler;
   List<WarningMessage> warnings;
   List<WarningMessage> errors;
+  List<WarningMessage> hints;
+  List<WarningMessage> infos;
   final Map<String, SourceFile> sourceFiles;
   Node parsedTree;
 
@@ -227,7 +228,7 @@
                 bool analyzeOnly: false,
                 bool emitJavaScript: true,
                 bool preserveComments: false})
-      : warnings = [], errors = [],
+      : warnings = [], errors = [], hints = [], infos = [],
         sourceFiles = new Map<String, SourceFile>(),
         super(enableTypeAssertions: enableTypeAssertions,
               enableMinification: enableMinification,
@@ -254,8 +255,8 @@
     libraryLoader.importLibrary(interceptorsLibrary, coreLibrary, null);
     libraryLoader.importLibrary(isolateHelperLibrary, coreLibrary, null);
 
-    assertMethod = jsHelperLibrary.find(buildSourceString('assertHelper'));
-    identicalFunction = coreLibrary.find(buildSourceString('identical'));
+    assertMethod = jsHelperLibrary.find('assertHelper');
+    identicalFunction = coreLibrary.find('identical');
 
     mainApp = mockLibrary(this, "");
     initializeSpecialClasses();
@@ -311,6 +312,22 @@
     reportDiagnostic(spanFromSpannable(node), '$message', api.Diagnostic.ERROR);
   }
 
+  void reportInfo(Spannable node,
+                   MessageKind errorCode,
+                   [Map arguments = const {}]) {
+    Message message = errorCode.message(arguments);
+    infos.add(new WarningMessage(node, message));
+    reportDiagnostic(spanFromSpannable(node), '$message', api.Diagnostic.INFO);
+  }
+
+  void reportHint(Spannable node,
+                   MessageKind errorCode,
+                   [Map arguments = const {}]) {
+    Message message = errorCode.message(arguments);
+    hints.add(new WarningMessage(node, message));
+    reportDiagnostic(spanFromSpannable(node), '$message', api.Diagnostic.HINT);
+  }
+
   void reportFatalError(Spannable node,
                         MessageKind errorCode,
                         [Map arguments = const {}]) {
@@ -321,8 +338,12 @@
     var diagnostic = new WarningMessage(null, message.message);
     if (kind == api.Diagnostic.ERROR) {
       errors.add(diagnostic);
-    } else {
+    } else if (kind == api.Diagnostic.WARNING) {
       warnings.add(diagnostic);
+    } else if (kind == api.Diagnostic.INFO) {
+      infos.add(diagnostic);
+    } else if (kind == api.Diagnostic.HINT) {
+      hints.add(diagnostic);
     }
     reportDiagnostic(span, "$message", kind);
   }
@@ -339,12 +360,11 @@
 
   bool get compilationFailed => !errors.isEmpty;
 
-  void clearWarnings() {
+  void clearMessages() {
     warnings = [];
-  }
-
-  void clearErrors() {
     errors = [];
+    hints = [];
+    infos = [];
   }
 
   CollectingTreeElements resolveStatement(String text) {
@@ -365,7 +385,7 @@
 
   resolverVisitor() {
     Element mockElement =
-        new ElementX(buildSourceString(''), ElementKind.FUNCTION,
+        new ElementX('', ElementKind.FUNCTION,
             mainApp.entryCompilationUnit);
     ResolverVisitor visitor =
         new ResolverVisitor(this, mockElement,
@@ -476,7 +496,7 @@
   return (uri, int begin, int end, String message, kind) {
     SourceFile sourceFile;
     if (uri == null) {
-      sourceFile = new SourceFile('analysis', text);
+      sourceFile = new StringSourceFile('analysis', text);
     } else {
       sourceFile = compiler.sourceFiles[uri.toString()];
     }
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index 3d8a353..94c3b57 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -16,8 +16,7 @@
     show CompilationUnitElementX,
          LibraryElementX;
 
-import "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart"
-    hide SourceString;
+import "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart";
 
 export "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart"
     show DiagnosticListener;
@@ -60,7 +59,7 @@
   withCurrentElement(Element element, f()) => f();
 }
 
-Token scan(String text) => new StringScanner(text).tokenize();
+Token scan(String text) => new StringScanner.fromString(text).tokenize();
 
 Node parseBodyCode(String text, Function parseMethod,
                    {DiagnosticListener diagnosticHandler}) {
@@ -98,7 +97,7 @@
                        diagnosticHandler: diagnosticHandler);
 }
 
-class MockFile extends SourceFile {
+class MockFile extends StringSourceFile {
   MockFile(text)
       : super('<string>', text);
 }
@@ -126,10 +125,3 @@
   return parseBodyCode(source, (parser, tokens) => parser.parseUnit(tokens),
                        diagnosticHandler: diagnosticHandler);
 }
-
-// TODO(ahe): We define this method to avoid having to import
-// the scanner in the tests. We should move SourceString to another
-// location instead.
-SourceString buildSourceString(String name) {
-  return new SourceString(name);
-}
diff --git a/tests/compiler/dart2js/parser_test.dart b/tests/compiler/dart2js/parser_test.dart
index 5cc7f55..322c47d 100644
--- a/tests/compiler/dart2js/parser_test.dart
+++ b/tests/compiler/dart2js/parser_test.dart
@@ -259,8 +259,8 @@
   FunctionExpression function = parseMember('operator -() => null;');
   Send name = function.name.asSend();
   Expect.isNotNull(name);
-  Expect.stringEquals('operator', name.receiver.source.stringValue);
-  Expect.stringEquals('-', name.selector.source.stringValue);
+  Expect.stringEquals('operator', name.receiver.source);
+  Expect.stringEquals('-', name.selector.source);
   Expect.isTrue(function.parameters.isEmpty);
   Expect.isNull(function.returnType);
   Expect.isNull(function.getOrSet);
diff --git a/tests/compiler/dart2js/partial_parser_test.dart b/tests/compiler/dart2js/partial_parser_test.dart
index 120b6a6..e0099f1 100644
--- a/tests/compiler/dart2js/partial_parser_test.dart
+++ b/tests/compiler/dart2js/partial_parser_test.dart
@@ -13,13 +13,13 @@
   PartialParser parser = new PartialParser(new Listener());
   Token token = scan('a < b;');
   token = parser.skipExpression(token);
-  Expect.equals(';', token.stringValue);
+  Expect.equals(';', token.value);
 
   token = scan('[a < b]').next;
   token = parser.skipExpression(token);
-  Expect.equals(']', token.stringValue);
+  Expect.equals(']', token.value);
 
   token = scan('a < b,');
   token = parser.skipExpression(token);
-  Expect.equals(',', token.stringValue);
+  Expect.equals(',', token.value);
 }
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 34bf187..05dca89 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -53,7 +53,7 @@
                 bool expectIsGetter: false,
                 bool expectIsFound: true,
                 bool expectIsRegular: false}) {
-  var element = lookup(buildSourceString(name));
+  var element = lookup(name);
   if (!expectIsFound) {
     Expect.isNull(element);
     return element;
@@ -343,16 +343,16 @@
     container.ensureResolved(compiler);
     container.parseNode(compiler);
 
-    void expect(String methodName, List warnings, List errors) {
-      compiler.warnings.clear();
-      compiler.errors.clear();
+    void expect(String methodName, List infos, List errors) {
+      compiler.clearMessages();
       compiler.resolver.resolveMethodElement(
           ensure(compiler, methodName, container.lookupLocalMember,
               expectIsPatched: true, checkHasBody: true));
-      Expect.equals(warnings.length, compiler.warnings.length,
-                    "Unexpected warnings: ${compiler.warnings} on $methodName");
-      for (int i = 0 ; i < warnings.length ; i++) {
-        Expect.equals(warnings[i], compiler.warnings[i].message.kind);
+      Expect.equals(0, compiler.warnings.length);
+      Expect.equals(infos.length, compiler.infos.length,
+                    "Unexpected infos: ${compiler.infos} on $methodName");
+      for (int i = 0 ; i < infos.length ; i++) {
+        Expect.equals(infos[i], compiler.infos[i].message.kind);
       }
       Expect.equals(errors.length, compiler.errors.length,
                     "Unexpected errors: ${compiler.errors} on $methodName");
@@ -551,8 +551,9 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
-    Expect.equals(1, compiler.warnings.length);
-    Expect.isTrue(compiler.warnings[0].message.kind ==
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
+    Expect.isTrue(compiler.infos[0].message.kind ==
         MessageKind.PATCH_POINT_TO_FUNCTION);
   }));
 }
@@ -578,8 +579,9 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
-    Expect.equals(1, compiler.warnings.length);
-    Expect.isTrue(compiler.warnings[0].message.kind ==
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
+    Expect.isTrue(compiler.infos[0].message.kind ==
         MessageKind.PATCH_POINT_TO_FUNCTION);
   }));
 }
@@ -597,9 +599,10 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NON_CLASS);
-    Expect.equals(1, compiler.warnings.length);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
     Expect.isTrue(
-        compiler.warnings[0].message.kind == MessageKind.PATCH_POINT_TO_CLASS);
+        compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_CLASS);
   }));
 }
 
@@ -616,9 +619,10 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NON_GETTER);
-    Expect.equals(1, compiler.warnings.length);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
     Expect.isTrue(
-        compiler.warnings[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
+        compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
   }));
 }
 
@@ -635,9 +639,10 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NO_GETTER);
-    Expect.equals(1, compiler.warnings.length);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
     Expect.isTrue(
-        compiler.warnings[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
+        compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
   }));
 }
 
@@ -654,9 +659,10 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NON_SETTER);
-    Expect.equals(1, compiler.warnings.length);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
     Expect.isTrue(
-        compiler.warnings[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
+        compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
   }));
 }
 
@@ -673,9 +679,10 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NO_SETTER);
-    Expect.equals(1, compiler.warnings.length);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
     Expect.isTrue(
-        compiler.warnings[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
+        compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
   }));
 }
 
@@ -692,9 +699,10 @@
     Expect.equals(1, compiler.errors.length);
     Expect.isTrue(
         compiler.errors[0].message.kind == MessageKind.PATCH_NON_FUNCTION);
-    Expect.equals(1, compiler.warnings.length);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(1, compiler.infos.length);
     Expect.isTrue(
-        compiler.warnings[0].message.kind ==
+        compiler.infos[0].message.kind ==
             MessageKind.PATCH_POINT_TO_FUNCTION);
   }));
 }
@@ -729,19 +737,19 @@
     // Check that a method just in the patch class is a target for a
     // typed selector.
     var selector = new Selector.call(
-        buildSourceString('method'), compiler.coreLibrary, 0);
+        'method', compiler.coreLibrary, 0);
     var typedSelector = new TypedSelector.exact(cls, selector);
     Element method =
-        cls.implementation.lookupLocalMember(buildSourceString('method'));
+        cls.implementation.lookupLocalMember('method');
     Expect.isTrue(selector.applies(method, compiler));
     Expect.isTrue(typedSelector.applies(method, compiler));
 
     // Check that the declaration method in the declaration class is a target
     // for a typed selector.
     selector = new Selector.call(
-        buildSourceString('clear'), compiler.coreLibrary, 0);
+        'clear', compiler.coreLibrary, 0);
     typedSelector = new TypedSelector.exact(cls, selector);
-    method = cls.lookupLocalMember(buildSourceString('clear'));
+    method = cls.lookupLocalMember('clear');
     Expect.isTrue(selector.applies(method, compiler));
     Expect.isTrue(typedSelector.applies(method, compiler));
 
diff --git a/tests/compiler/dart2js/private_test.dart b/tests/compiler/dart2js/private_test.dart
index 2bb9f19..9857d54 100644
--- a/tests/compiler/dart2js/private_test.dart
+++ b/tests/compiler/dart2js/private_test.dart
@@ -7,8 +7,7 @@
 import 'mock_compiler.dart';
 
 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
-    hide SourceString;
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart';
 
 const String PRIVATE_SOURCE_URI = 'src:private';
 const String PRIVATE_SOURCE = '''
diff --git a/tests/compiler/dart2js/reexport_handled_test.dart b/tests/compiler/dart2js/reexport_handled_test.dart
index 401afb1..ff81d14 100644
--- a/tests/compiler/dart2js/reexport_handled_test.dart
+++ b/tests/compiler/dart2js/reexport_handled_test.dart
@@ -48,7 +48,7 @@
 
 Element findInExports(LibraryElement library, String name) {
   for (var export in library.exports) {
-    if (export.name.slowToString() == name) {
+    if (export.name == name) {
       return export;
     }
   }
diff --git a/tests/compiler/dart2js/resolution_test.dart b/tests/compiler/dart2js/resolution_test.dart
index ac97858..4f47d01 100644
--- a/tests/compiler/dart2js/resolution_test.dart
+++ b/tests/compiler/dart2js/resolution_test.dart
@@ -102,14 +102,14 @@
 
 void testHasRuntimeType(String code) {
   test(code, (compiler) {
-    var element = compiler.findHelper(buildSourceString('createRuntimeType'));
+    var element = compiler.findHelper('createRuntimeType');
     Expect.isTrue(compiler.enqueuer.resolution.isProcessed(element));
   });
 }
 
 main() {
   test(NO_RUNTIME_TYPE, (compiler) {
-    var element = compiler.findHelper(buildSourceString('createRuntimeType'));
+    var element = compiler.findHelper('createRuntimeType');
     Expect.isFalse(compiler.enqueuer.resolution.isProcessed(element));
   });
 
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index eb95b7d..a6a382c 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -47,7 +47,7 @@
     Identifier id = buildIdentifier(name);
     final VariableElement variableElement = visitor.visit(id);
     MethodScope scope = visitor.scope;
-    Expect.equals(variableElement, scope.elements[buildSourceString(name)]);
+    Expect.equals(variableElement, scope.elements[name]);
   }
   return compiler;
 }
@@ -97,9 +97,9 @@
 class C extends B implements L1 {}
 """);
   compiler.resolveStatement("C c;");
-  ClassElement classA = compiler.mainApp.find(buildSourceString("A"));
-  ClassElement classB = compiler.mainApp.find(buildSourceString("B"));
-  ClassElement classC = compiler.mainApp.find(buildSourceString("C"));
+  ClassElement classA = compiler.mainApp.find("A");
+  ClassElement classB = compiler.mainApp.find("B");
+  ClassElement classC = compiler.mainApp.find("C");
   Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString());
   Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]',
                 classB.allSupertypes.toString());
@@ -113,7 +113,7 @@
 class Bar extends Foo implements X<Bar> {}
 """);
   compiler.resolveStatement("Bar bar;");
-  ClassElement classBar = compiler.mainApp.find(buildSourceString("Bar"));
+  ClassElement classBar = compiler.mainApp.find("Bar");
   Expect.equals('[ Foo, X<Bar>, X<Foo>, Object ]',
                 classBar.allSupertypes.toString());
 }
@@ -139,7 +139,7 @@
   MockCompiler compiler = new MockCompiler();
   ResolverVisitor visitor = compiler.resolverVisitor();
   compiler.parseScript('class Foo<T, U> {}');
-  ClassElement foo = compiler.mainApp.find(buildSourceString('Foo'));
+  ClassElement foo = compiler.mainApp.find('Foo');
   matchResolvedTypes(visitor, 'Foo<int, String> x;', 'Foo',
                      [compiler.intClass, compiler.stringClass]);
   matchResolvedTypes(visitor, 'Foo<Foo, Foo> x;', 'Foo',
@@ -167,11 +167,11 @@
                        '  foo(Foo<T> f) {}'
                        '  bar() { g(Foo<T> f) {}; g(); }'
                        '}');
-  foo = compiler.mainApp.find(buildSourceString('Foo'));
+  foo = compiler.mainApp.find('Foo');
   foo.ensureResolved(compiler);
-  foo.lookupLocalMember(buildSourceString('t')).computeType(compiler);;
-  foo.lookupLocalMember(buildSourceString('foo')).computeType(compiler);;
-  compiler.resolver.resolve(foo.lookupLocalMember(buildSourceString('bar')));
+  foo.lookupLocalMember('t').computeType(compiler);;
+  foo.lookupLocalMember('foo').computeType(compiler);;
+  compiler.resolver.resolve(foo.lookupLocalMember('bar'));
   Expect.equals(0, compiler.warnings.length);
   Expect.equals(0, compiler.errors.length);
 }
@@ -183,10 +183,10 @@
   compiler.parseScript(script);
   compiler.resolveStatement("B b;");
 
-  ClassElement classB = compiler.mainApp.find(buildSourceString("B"));
-  FunctionElement fooB = classB.lookupLocalMember(buildSourceString("foo"));
-  ClassElement classA = compiler.mainApp.find(buildSourceString("A"));
-  FunctionElement fooA = classA.lookupLocalMember(buildSourceString("foo"));
+  ClassElement classB = compiler.mainApp.find("B");
+  FunctionElement fooB = classB.lookupLocalMember("foo");
+  ClassElement classA = compiler.mainApp.find("A");
+  FunctionElement fooA = classA.lookupLocalMember("foo");
 
   ResolverVisitor visitor =
       new ResolverVisitor(compiler, fooB, new CollectingTreeElements(fooB));
@@ -204,9 +204,9 @@
   MockCompiler compiler = new MockCompiler();
   compiler.parseScript("class Foo { foo() { return this; } }");
   compiler.resolveStatement("Foo foo;");
-  ClassElement fooElement = compiler.mainApp.find(buildSourceString("Foo"));
+  ClassElement fooElement = compiler.mainApp.find("Foo");
   FunctionElement funElement =
-      fooElement.lookupLocalMember(buildSourceString("foo"));
+      fooElement.lookupLocalMember("foo");
   ResolverVisitor visitor =
       new ResolverVisitor(compiler, funElement,
                           new CollectingTreeElements(funElement));
@@ -227,9 +227,9 @@
   compiler = new MockCompiler();
   compiler.parseScript("class Foo { static foo() { return this; } }");
   compiler.resolveStatement("Foo foo;");
-  fooElement = compiler.mainApp.find(buildSourceString("Foo"));
+  fooElement = compiler.mainApp.find("Foo");
   funElement =
-      fooElement.lookupLocalMember(buildSourceString("foo"));
+      fooElement.lookupLocalMember("foo");
   visitor = new ResolverVisitor(compiler, funElement,
                                 new CollectingTreeElements(funElement));
   function = funElement.parseNode(compiler);
@@ -443,7 +443,7 @@
       compiler.warnings[0].message);
   VariableDefinitions definition = compiler.parsedTree;
   Expect.equals(warningNode, definition.type);
-  compiler.clearWarnings();
+  compiler.clearMessages();
 
   // Test that there is no warning after defining Foo.
   compiler.parseScript("class Foo {}");
@@ -465,7 +465,7 @@
   var cannotResolveBar = new Message(MessageKind.CANNOT_EXTEND_MALFORMED,
                                      {'typeName': 'Bar'}, false);
   Expect.equals(cannotResolveBar, compiler.errors[0].message);
-  compiler.clearErrors();
+  compiler.clearMessages();
 
   compiler = new MockCompiler();
   compiler.parseScript("class Foo extends Bar {}");
@@ -473,8 +473,8 @@
   Map mapping = compiler.resolveStatement("Foo bar;").map;
   Expect.equals(2, mapping.length);
 
-  ClassElement fooElement = compiler.mainApp.find(buildSourceString('Foo'));
-  ClassElement barElement = compiler.mainApp.find(buildSourceString('Bar'));
+  ClassElement fooElement = compiler.mainApp.find('Foo');
+  ClassElement barElement = compiler.mainApp.find('Bar');
   Expect.equals(barElement.computeType(compiler),
                 fooElement.supertype);
   Expect.isTrue(fooElement.interfaces.isEmpty);
@@ -490,7 +490,7 @@
       new Message(
           MessageKind.CANNOT_RESOLVE_TYPE.warning, {'typeName': 'var'}, false),
       compiler.errors[0].message);
-  compiler.clearErrors();
+  compiler.clearMessages();
 }
 
 testOneInterface() {
@@ -502,7 +502,7 @@
       new Message(
           MessageKind.CANNOT_RESOLVE_TYPE.warning, {'typeName': 'bar'}, false),
       compiler.errors[0].message);
-  compiler.clearErrors();
+  compiler.clearMessages();
 
   // Add the abstract class to the world and make sure everything is setup
   // correctly.
@@ -512,8 +512,8 @@
       new ResolverVisitor(compiler, null, new CollectingTreeElements(null));
   compiler.resolveStatement("Foo bar;");
 
-  ClassElement fooElement = compiler.mainApp.find(buildSourceString('Foo'));
-  ClassElement barElement = compiler.mainApp.find(buildSourceString('Bar'));
+  ClassElement fooElement = compiler.mainApp.find('Foo');
+  ClassElement barElement = compiler.mainApp.find('Bar');
 
   Expect.equals(null, barElement.supertype);
   Expect.isTrue(barElement.interfaces.isEmpty);
@@ -529,9 +529,9 @@
       "abstract class I1 {} abstract class I2 {} class C implements I1, I2 {}");
   compiler.resolveStatement("Foo bar;");
 
-  ClassElement c = compiler.mainApp.find(buildSourceString('C'));
-  Element i1 = compiler.mainApp.find(buildSourceString('I1'));
-  Element i2 = compiler.mainApp.find(buildSourceString('I2'));
+  ClassElement c = compiler.mainApp.find('C');
+  Element i1 = compiler.mainApp.find('I1');
+  Element i2 = compiler.mainApp.find('I2');
 
   Expect.equals(2, length(c.interfaces));
   Expect.equals(i1.computeType(compiler), at(c.interfaces, 0));
@@ -552,15 +552,15 @@
     }
   });
   Expect.equals(ElementKind.FUNCTION, element.kind);
-  Expect.equals(buildSourceString('f'), element.name);
+  Expect.equals('f', element.name);
   Expect.equals(element.parseNode(compiler), node);
 }
 
 testNewExpression() {
   MockCompiler compiler = new MockCompiler();
   compiler.parseScript("class A {} foo() { print(new A()); }");
-  ClassElement aElement = compiler.mainApp.find(buildSourceString('A'));
-  FunctionElement fooElement = compiler.mainApp.find(buildSourceString('foo'));
+  ClassElement aElement = compiler.mainApp.find('A');
+  FunctionElement fooElement = compiler.mainApp.find('foo');
   Expect.isNotNull(aElement);
   Expect.isNotNull(fooElement);
 
@@ -579,7 +579,7 @@
   String script = "class A {} foo() { print(new A(42)); }";
   MockCompiler compiler = new MockCompiler();
   compiler.parseScript(script);
-  FunctionElement fooElement = compiler.mainApp.find(buildSourceString('foo'));
+  FunctionElement fooElement = compiler.mainApp.find('foo');
   Expect.isNotNull(fooElement);
   fooElement.parseNode(compiler);
   compiler.resolver.resolve(fooElement);
@@ -592,15 +592,15 @@
 testTopLevelFields() {
   MockCompiler compiler = new MockCompiler();
   compiler.parseScript("int a;");
-  VariableElement element = compiler.mainApp.find(buildSourceString("a"));
+  VariableElement element = compiler.mainApp.find("a");
   Expect.equals(ElementKind.FIELD, element.kind);
   VariableDefinitions node = element.variables.parseNode(compiler);
   Identifier typeName = node.type.typeName;
-  Expect.equals(typeName.source.slowToString(), 'int');
+  Expect.equals(typeName.source, 'int');
 
   compiler.parseScript("var b, c;");
-  VariableElement bElement = compiler.mainApp.find(buildSourceString("b"));
-  VariableElement cElement = compiler.mainApp.find(buildSourceString("c"));
+  VariableElement bElement = compiler.mainApp.find("b");
+  VariableElement cElement = compiler.mainApp.find("c");
   Expect.equals(ElementKind.FIELD, bElement.kind);
   Expect.equals(ElementKind.FIELD, cElement.kind);
   Expect.isTrue(bElement != cElement);
@@ -616,16 +616,17 @@
                    String constructor, int expectedElementCount,
                    {List expectedWarnings: const [],
                     List expectedErrors: const [],
+                    List expectedInfos: const [],
                     String corelib: DEFAULT_CORELIB}) {
   MockCompiler compiler = new MockCompiler(coreSource: corelib);
   compiler.parseScript(script);
   compiler.resolveStatement(statement);
   ClassElement classElement =
-      compiler.mainApp.find(buildSourceString(className));
+      compiler.mainApp.find(className);
   Element element;
   if (constructor != '') {
     element = classElement.lookupConstructor(
-        new Selector.callConstructor(buildSourceString(constructor),
+        new Selector.callConstructor(constructor,
                                      classElement.getLibrary()));
   } else {
     element = classElement.lookupConstructor(
@@ -642,10 +643,11 @@
 
   compareWarningKinds(script, expectedWarnings, compiler.warnings);
   compareWarningKinds(script, expectedErrors, compiler.errors);
+  compareWarningKinds(script, expectedInfos, compiler.infos);
 }
 
 testClassHierarchy() {
-  final MAIN = buildSourceString("main");
+  final MAIN = "main";
   MockCompiler compiler = new MockCompiler();
   compiler.parseScript("""class A extends B {}
                           class B extends A {}
@@ -680,7 +682,7 @@
   compiler.resolver.resolve(mainElement);
   Expect.equals(0, compiler.warnings.length);
   Expect.equals(0, compiler.errors.length);
-  ClassElement aElement = compiler.mainApp.find(buildSourceString("A"));
+  ClassElement aElement = compiler.mainApp.find("A");
   Link<DartType> supertypes = aElement.allSupertypes;
   Expect.equals(<String>['B', 'C', 'Object'].toString(),
                 asSortedStrings(supertypes).toString());
@@ -695,7 +697,7 @@
   compiler.resolver.resolve(mainElement);
   Expect.equals(0, compiler.warnings.length);
   Expect.equals(0, compiler.errors.length);
-  aElement = compiler.mainApp.find(buildSourceString("C"));
+  aElement = compiler.mainApp.find("C");
   supertypes = aElement.allSupertypes;
   // Object is once per inheritance path, that is from both A and I.
   Expect.equals(<String>['A<int>', 'B<bool, String>', 'I<bool, List<String>>',
@@ -711,7 +713,7 @@
   compiler.resolver.resolve(mainElement);
   Expect.equals(0, compiler.warnings.length);
   Expect.equals(0, compiler.errors.length);
-  aElement = compiler.mainApp.find(buildSourceString("E"));
+  aElement = compiler.mainApp.find("E");
   supertypes = aElement.allSupertypes;
   Expect.equals(<String>['A<E>', 'D', 'Object'].toString(),
                 asSortedStrings(supertypes).toString());
@@ -739,7 +741,7 @@
                 A() : this.foo = 1, this.foo = 2;
               }""";
   resolveConstructor(script, "A a = new A();", "A", "", 2,
-                     expectedWarnings: [MessageKind.ALREADY_INITIALIZED],
+                     expectedInfos: [MessageKind.ALREADY_INITIALIZED],
                      expectedErrors: [MessageKind.DUPLICATE_INITIALIZER]);
 
   script = """class A {
@@ -860,12 +862,12 @@
 testToString() {
   final script = r"class C { toString() => 'C'; } main() { '${new C()}'; }";
   asyncTest(() => compileScript(script).then((compiler) {
-    checkMemberResolved(compiler, 'C', buildSourceString('toString'));
+    checkMemberResolved(compiler, 'C', 'toString');
   }));
 }
 
 operatorName(op, isUnary) {
-  return Elements.constructOperatorName(new SourceString(op), isUnary);
+  return Elements.constructOperatorName(op, isUnary);
 }
 
 testIndexedOperator() {
@@ -918,22 +920,25 @@
         new A() == new B();
       }""";
   asyncTest(() => compileScript(script).then((compiler) {
-    Expect.equals(1, compiler.warnings.length);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(0, compiler.infos.length);
+    Expect.equals(1, compiler.hints.length);
     Expect.equals(MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE,
-                  compiler.warnings[0].message.kind);
+                  compiler.hints[0].message.kind);
     Expect.equals(0, compiler.errors.length);
   }));
 }
 
 testConstConstructorAndNonFinalFields() {
-  void expect(compiler, List errors, List warnings) {
+  void expect(compiler, List errors, List infos) {
     Expect.equals(errors.length, compiler.errors.length);
     for (int i = 0 ; i < errors.length ; i++) {
       Expect.equals(errors[i], compiler.errors[i].message.kind);
     }
-    Expect.equals(warnings.length, compiler.warnings.length);
-    for (int i = 0 ; i < warnings.length ; i++) {
-      Expect.equals(warnings[i], compiler.warnings[i].message.kind);
+    Expect.equals(0, compiler.warnings.length);
+    Expect.equals(infos.length, compiler.infos.length);
+    for (int i = 0 ; i < infos.length ; i++) {
+      Expect.equals(infos[i], compiler.infos[i].message.kind);
     }
   }
 
diff --git a/tests/compiler/dart2js/scanner_offset_length_test.dart b/tests/compiler/dart2js/scanner_offset_length_test.dart
index 6f8db24..798057d 100644
--- a/tests/compiler/dart2js/scanner_offset_length_test.dart
+++ b/tests/compiler/dart2js/scanner_offset_length_test.dart
@@ -4,18 +4,17 @@
 
 import "package:expect/expect.dart";
 import '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/scanner/scanner_implementation.dart';
 
 Token scan(String text) =>
-    new StringScanner(text, includeComments: true).tokenize();
+    new StringScanner.fromString(text, includeComments: true).tokenize();
 
 check(String text) {
   Token token = scan(text);
   while (token.kind != EOF_TOKEN) {
-    Expect.equals(token.slowToString().length, token.slowCharCount);
+    Expect.equals(token.value.length, token.charCount);
 
     var start = token.charOffset;
-    var end = token.charOffset + token.slowCharCount;
+    var end = token.charOffset + token.charCount;
 
     Expect.isTrue(start < text.length,
         'start=$start < text.length=${text.length}: $text');
@@ -27,8 +26,8 @@
 
     var substring = text.substring(start, end);
 
-    Expect.stringEquals(token.slowToString(), substring,
-        'token.slowToString()=${token.slowToString()} == '
+    Expect.stringEquals(token.value, substring,
+        'token.value=${token.value} == '
         'text.substring(start,end)=${substring}: $text');
 
     print('$text: [$start,$end]:$token');
diff --git a/tests/compiler/dart2js/scanner_test.dart b/tests/compiler/dart2js/scanner_test.dart
index da8f032..2945bd5 100644
--- a/tests/compiler/dart2js/scanner_test.dart
+++ b/tests/compiler/dart2js/scanner_test.dart
@@ -3,65 +3,71 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import 'dart:collection';
-import 'dart:utf';
 import '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/scanner/scanner_implementation.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/util/characters.dart';
-part '../../../sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart';
-part '../../../sdk/lib/_internal/compiler/implementation/scanner/byte_array_scanner.dart';
+import 'dart:typed_data';
 
-Token scan(List<int> bytes) => new ByteArrayScanner(bytes).tokenize();
+Token scan(List<int> bytes) => new Utf8BytesScanner.fromBytes(bytes).tokenize();
+
+Token scanUTF8(List<int> bytes) {
+  int l = bytes.length;
+  List<int> stringLiteral = new Uint8List(l + 3);
+  stringLiteral[0] = 0x27; // single quote
+  stringLiteral[l+1] = 0x27; // single quote
+  stringLiteral[l+2] = $EOF;
+  for (int i = 0; i < l; i++) {
+    stringLiteral[i+1] = bytes[i];
+  }
+  return new Utf8BytesScanner.fromBytes(stringLiteral).tokenize();
+}
 
 bool isRunningOnJavaScript() => identical(1, 1.0);
 
 main() {
   // Google favorite: "Îñţérñåţîöñåļîžåţîờñ".
-  Token token = scan([0xc3, 0x8e, 0xc3, 0xb1, 0xc5, 0xa3, 0xc3, 0xa9, 0x72,
-                      0xc3, 0xb1, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xc3,
-                      0xb6, 0xc3, 0xb1, 0xc3, 0xa5, 0xc4, 0xbc, 0xc3, 0xae,
-                      0xc5, 0xbe, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xe1,
-                      0xbb, 0x9d, 0xc3, 0xb1, $EOF]);
-  Expect.stringEquals("Îñţérñåţîöñåļîžåţîờñ", token.value.slowToString());
+  Token token = scanUTF8([0xc3, 0x8e, 0xc3, 0xb1, 0xc5, 0xa3, 0xc3, 0xa9, 0x72,
+                          0xc3, 0xb1, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xc3,
+                          0xb6, 0xc3, 0xb1, 0xc3, 0xa5, 0xc4, 0xbc, 0xc3, 0xae,
+                          0xc5, 0xbe, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xe1,
+                          0xbb, 0x9d, 0xc3, 0xb1]);
+  Expect.stringEquals("'Îñţérñåţîöñåļîžåţîờñ'", token.value);
 
   // Blueberry porridge in Danish: "blåbærgrød".
-  token = scan([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6, 0x72, 0x67, 0x72,
-                0xc3, 0xb8, 0x64, $EOF]);
-  Expect.stringEquals("blåbærgrød", token.value.slowToString());
+  token = scanUTF8([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6, 0x72, 0x67, 0x72,
+                    0xc3, 0xb8, 0x64]);
+  Expect.stringEquals("'blåbærgrød'", token.value);
 
   // "சிவா அணாமாைல", that is "Siva Annamalai" in Tamil.
-  token = scan([0xe0, 0xae, 0x9a, 0xe0, 0xae, 0xbf, 0xe0, 0xae, 0xb5, 0xe0,
-                0xae, 0xbe, 0x20, 0xe0, 0xae, 0x85, 0xe0, 0xae, 0xa3, 0xe0,
-                0xae, 0xbe, 0xe0, 0xae, 0xae, 0xe0, 0xae, 0xbe, 0xe0, 0xaf,
-                0x88, 0xe0, 0xae, 0xb2, $EOF]);
-  Expect.stringEquals("சிவா", token.value.slowToString());
-  Expect.stringEquals("அணாமாைல", token.next.value.slowToString());
+  token = scanUTF8([0xe0, 0xae, 0x9a, 0xe0, 0xae, 0xbf, 0xe0, 0xae, 0xb5, 0xe0,
+                    0xae, 0xbe, 0x20, 0xe0, 0xae, 0x85, 0xe0, 0xae, 0xa3, 0xe0,
+                    0xae, 0xbe, 0xe0, 0xae, 0xae, 0xe0, 0xae, 0xbe, 0xe0, 0xaf,
+                    0x88, 0xe0, 0xae, 0xb2]);
+  Expect.stringEquals("'சிவா அணாமாைல'", token.value);
 
   // "िसवा अणामालै", that is "Siva Annamalai" in Devanagari.
-  token = scan([0xe0, 0xa4, 0xbf, 0xe0, 0xa4, 0xb8, 0xe0, 0xa4, 0xb5, 0xe0,
-                0xa4, 0xbe, 0x20, 0xe0, 0xa4, 0x85, 0xe0, 0xa4, 0xa3, 0xe0,
-                0xa4, 0xbe, 0xe0, 0xa4, 0xae, 0xe0, 0xa4, 0xbe, 0xe0, 0xa4,
-                0xb2, 0xe0, 0xa5, 0x88, $EOF]);
-  Expect.stringEquals("िसवा", token.value.slowToString());
-  Expect.stringEquals("अणामालै", token.next.value.slowToString());
+  token = scanUTF8([0xe0, 0xa4, 0xbf, 0xe0, 0xa4, 0xb8, 0xe0, 0xa4, 0xb5, 0xe0,
+                    0xa4, 0xbe, 0x20, 0xe0, 0xa4, 0x85, 0xe0, 0xa4, 0xa3, 0xe0,
+                    0xa4, 0xbe, 0xe0, 0xa4, 0xae, 0xe0, 0xa4, 0xbe, 0xe0, 0xa4,
+                    0xb2, 0xe0, 0xa5, 0x88]);
+  Expect.stringEquals("'िसवा अणामालै'", token.value);
 
   if (!isRunningOnJavaScript()) {
     // DESERET CAPITAL LETTER BEE, unicode 0x10412(0xD801+0xDC12)
     // UTF-8: F0 90 90 92
-    token = scan([0xf0, 0x90, 0x90, 0x92, $EOF]);
-    Expect.stringEquals("𐐒", token.value.slowToString());
+    token = scanUTF8([0xf0, 0x90, 0x90, 0x92]);
+    Expect.stringEquals("'𐐒'", token.value);
   } else {
     print('Skipping non-BMP character test');
   }
 
   // Regression test for issue 1761.
   // "#!"
-  token = scan([0x23, 0x21, $EOF]);
+  token = scan([0x23, 0x21]);
   Expect.equals(token.info, EOF_INFO); // Treated as a comment.
 
   // Regression test for issue 1761.
   // "#! Hello, World!"
   token = scan([0x23, 0x21, 0x20, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20,
-                0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, $EOF]);
+                0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21]);
   Expect.equals(token.info, EOF_INFO); // Treated as a comment.
 }
diff --git a/tests/compiler/dart2js/setlet_test.dart b/tests/compiler/dart2js/setlet_test.dart
new file mode 100644
index 0000000..38982d7
--- /dev/null
+++ b/tests/compiler/dart2js/setlet_test.dart
@@ -0,0 +1,69 @@
+// 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 '../../../sdk/lib/_internal/compiler/implementation/util/setlet.dart';
+
+main() {
+  for (int i = 1; i <= 32; i++) {
+    test(i);
+  }
+}
+
+test(int size) {
+  var setlet = new Setlet();
+  for (int i = 0; i < size; i++) {
+    Expect.isTrue(setlet.isEmpty == (i == 0));
+    setlet.add(i);
+    Expect.equals(i + 1, setlet.length);
+    Expect.isFalse(setlet.isEmpty);
+    for (int j = 0; j < size + size; j++) {
+      Expect.isTrue(setlet.contains(j) == (j <= i));
+    }
+    Expect.isTrue(setlet.remove(i));
+    Expect.isFalse(setlet.remove(i + 1));
+    setlet.add(i);
+
+    List expectedElements = [];
+    for (int j = 0; j <= i; j++) expectedElements.add(j);
+
+    List actualElements = [];
+    setlet.forEach((each) => actualElements.add(each));
+    Expect.listEquals(expectedElements, actualElements);
+
+    actualElements = [];
+    for (var each in setlet) actualElements.add(each);
+    Expect.listEquals(expectedElements, actualElements);
+  }
+
+  for (int i = 0; i < size; i++) {
+    Expect.equals(size, setlet.length);
+
+    // Try removing all possible ranges one by one and re-add them.
+    for (int k = size; k > i; --k) {
+      for (int j = i; j < k; j++) {
+        Expect.isTrue(setlet.remove(j));
+        int expectedSize = size - (j - i + 1);
+        Expect.equals(expectedSize, setlet.length);
+        Expect.isFalse(setlet.remove(j));
+        Expect.isFalse(setlet.contains(j));
+
+        Expect.isFalse(setlet.contains(null));
+        setlet.add(null);
+        Expect.equals(expectedSize + 1, setlet.length);
+        Expect.isTrue(setlet.contains(null));
+        Expect.isTrue(setlet.remove(null));
+        Expect.equals(expectedSize, setlet.length);
+        Expect.isFalse(setlet.remove(null));
+      }
+
+      for (int j = i; j < k; j++) {
+        setlet.add(j);
+      }
+    }
+
+    Expect.equals(size, setlet.length);
+    Expect.isTrue(setlet.contains(i));
+  }
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_callers_test.dart b/tests/compiler/dart2js/simple_inferrer_callers_test.dart
index 6b1381b..165dc18 100644
--- a/tests/compiler/dart2js/simple_inferrer_callers_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_callers_test.dart
@@ -43,9 +43,9 @@
   asyncTest(() => compiler.runCompiler(uri).then((_) {
     var mainElement = findElement(compiler, 'main');
     var classA = findElement(compiler, 'A');
-    var fieldA = classA.lookupLocalMember(buildSourceString('field'));
+    var fieldA = classA.lookupLocalMember('field');
     var classB = findElement(compiler, 'B');
-    var fieldB = classB.lookupLocalMember(buildSourceString('field'));;
+    var fieldB = classB.lookupLocalMember('field');
 
     Expect.isTrue(inferrer.getCallersOf(fieldA).contains(mainElement));
     Expect.isTrue(inferrer.getCallersOf(fieldB).contains(mainElement));
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index 4746044..e087982 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -5,7 +5,6 @@
 import 'package:expect/expect.dart';
 import "package:async_helper/async_helper.dart";
 import 'compiler_helper.dart';
-import 'parser_helper.dart' show buildSourceString;
 
 const String TEST = """
 returnInt1() {
@@ -140,7 +139,7 @@
 
     checkReturnInClass(String className, String methodName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(methodName));
+      var element = cls.lookupLocalMember(methodName);
       Expect.equals(type,
           typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
     }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
index fa7b6f5..a18aa9a 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
@@ -32,7 +32,7 @@
 
     checkFieldTypeInClass(String className, String fieldName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(fieldName));
+      var element = cls.lookupLocalMember(fieldName);
       Expect.equals(type, typesInferrer.getTypeOfElement(element));
     }
 
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
index 9c76b76..592346b 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
@@ -31,7 +31,7 @@
 
     checkFieldTypeInClass(String className, String fieldName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(fieldName));
+      var element = cls.lookupLocalMember(fieldName);
       Expect.equals(type,
           typesInferrer.getTypeOfElement(element).simplify(compiler));
     }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 6eaa89b..7c195c3 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -34,7 +34,7 @@
 
     checkFieldTypeInClass(String className, String fieldName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(fieldName));
+      var element = cls.lookupLocalMember(fieldName);
       Expect.equals(type,
           typesInferrer.getTypeOfElement(element).simplify(compiler));
     }
diff --git a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
index fdb9cc8..0b1e8b0 100644
--- a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
@@ -70,7 +70,7 @@
 
     checkReturnInClass(String className, String methodName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(methodName));
+      var element = cls.lookupLocalMember(methodName);
       Expect.equals(type,
           typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
           methodName);
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 879f819..93d2737 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -793,7 +793,7 @@
 
     checkReturnInClass(String className, String methodName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(methodName));
+      var element = cls.lookupLocalMember(methodName);
       Expect.equals(type,
           typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
     }
@@ -818,7 +818,7 @@
 
     checkFactoryConstructor(String className, String factoryName) {
       var cls = findElement(compiler, className);
-      var element = cls.localLookup(buildSourceString(factoryName));
+      var element = cls.localLookup(factoryName);
       Expect.equals(new TypeMask.nonNullExact(cls),
                     typesInferrer.getReturnTypeOfElement(element));
     }
diff --git a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
index 35a2994..3244287 100644
--- a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
@@ -37,7 +37,7 @@
 
     checkReturnInClass(String className, String methodName, type) {
       var cls = findElement(compiler, className);
-      var element = cls.lookupLocalMember(buildSourceString(methodName));
+      var element = cls.lookupLocalMember(methodName);
       Expect.equals(type, typesInferrer.getReturnTypeOfElement(element));
     }
 
diff --git a/tests/compiler/dart2js/source_mapping_test.dart b/tests/compiler/dart2js/source_mapping_test.dart
index 8d404f8..752d05a 100644
--- a/tests/compiler/dart2js/source_mapping_test.dart
+++ b/tests/compiler/dart2js/source_mapping_test.dart
@@ -28,7 +28,7 @@
   }
   String code = codeWithMarkers.replaceAll('@', '');
 
-  SourceFile sourceFile = new SourceFile('<test script>', code);
+  SourceFile sourceFile = new StringSourceFile('<test script>', code);
   asyncTest(() => compileAll(sourceFile).then((CodeBuffer buffer) {
     Set<int> locations = new Set<int>();
     buffer.forEachSourceLocation((int offset, var sourcePosition) {
@@ -41,8 +41,8 @@
       int expectedLocation = expectedLocations[i];
       if (!locations.contains(expectedLocation)) {
         int originalLocation = expectedLocation + i;
-        SourceFile sourceFileWithMarkers = new SourceFile('<test script>',
-                                                          codeWithMarkers);
+        SourceFile sourceFileWithMarkers =
+            new StringSourceFile('<test script>', codeWithMarkers);
         String message = sourceFileWithMarkers.getLocationMessage(
             'Missing location', originalLocation, originalLocation + 1, true,
             (s) => s);
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 8277044..00c15d3 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
 import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/util/util.dart';
@@ -14,8 +13,7 @@
 import '../../../sdk/lib/_internal/compiler/implementation/elements/modelx.dart'
     show ElementX, CompilationUnitElementX;
 
-import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
-    hide SourceString;
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart';
 
 import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
 
@@ -58,7 +56,8 @@
                 testFunctionTypeLookup,
                 testTypedefLookup,
                 testTypeLiteral,
-                testInitializers];
+                testInitializers,
+                testTypePromotionHints];
   for (Function test in tests) {
     setup();
     test();
@@ -94,13 +93,13 @@
 testFor() {
   analyze("for (var x;true;x = x + 1) {}");
   analyze("for (var x;null;x = x + 1) {}");
-  analyze("for (var x;0;x = x + 1) {}", NOT_ASSIGNABLE);
-  analyze("for (var x;'';x = x + 1) {}", NOT_ASSIGNABLE);
+  analyze("for (var x;0;x = x + 1) {}", warnings: NOT_ASSIGNABLE);
+  analyze("for (var x;'';x = x + 1) {}", warnings: NOT_ASSIGNABLE);
 
    analyze("for (;true;) {}");
    analyze("for (;null;) {}");
-   analyze("for (;0;) {}", NOT_ASSIGNABLE);
-   analyze("for (;'';) {}", NOT_ASSIGNABLE);
+   analyze("for (;0;) {}", warnings: NOT_ASSIGNABLE);
+   analyze("for (;'';) {}", warnings: NOT_ASSIGNABLE);
 
   // Foreach tests
 //  TODO(karlklose): for each is not yet implemented.
@@ -114,15 +113,15 @@
 testWhile() {
   analyze("while (true) {}");
   analyze("while (null) {}");
-  analyze("while (0) {}", NOT_ASSIGNABLE);
-  analyze("while ('') {}", NOT_ASSIGNABLE);
+  analyze("while (0) {}", warnings: NOT_ASSIGNABLE);
+  analyze("while ('') {}", warnings: NOT_ASSIGNABLE);
 
   analyze("do {} while (true);");
   analyze("do {} while (null);");
-  analyze("do {} while (0);", NOT_ASSIGNABLE);
-  analyze("do {} while ('');", NOT_ASSIGNABLE);
-  analyze("do { int i = 0.5; } while (true);", NOT_ASSIGNABLE);
-  analyze("do { int i = 0.5; } while (null);", NOT_ASSIGNABLE);
+  analyze("do {} while (0);", warnings: NOT_ASSIGNABLE);
+  analyze("do {} while ('');", warnings: NOT_ASSIGNABLE);
+  analyze("do { int i = 0.5; } while (true);", warnings: NOT_ASSIGNABLE);
+  analyze("do { int i = 0.5; } while (null);", warnings: NOT_ASSIGNABLE);
 }
 
 testTry() {
@@ -130,27 +129,32 @@
   analyze("try {} catch (e) { int i = e;} finally {}");
   analyze("try {} catch (e, s) { int i = e; StackTrace j = s; } finally {}");
   analyze("try {} on String catch (e) {} finally {}");
-  analyze("try { int i = ''; } finally {}", NOT_ASSIGNABLE);
-  analyze("try {} finally { int i = ''; }", NOT_ASSIGNABLE);
+  analyze("try { int i = ''; } finally {}", warnings: NOT_ASSIGNABLE);
+  analyze("try {} finally { int i = ''; }", warnings: NOT_ASSIGNABLE);
   analyze("try {} on String catch (e) { int i = e; } finally {}",
-      NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("try {} catch (e, s) { int i = e; int j = s; } finally {}",
-      NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("try {} on String catch (e, s) { int i = e; int j = s; } finally {}",
-      [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
+          warnings: [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
 }
 
 
 testSwitch() {
   analyze("switch (0) { case 1: break; case 2: break; }");
   analyze("switch (0) { case 1: int i = ''; break; case 2: break; }",
-      NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("switch (0) { case '': break; }",
-      NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("switch ('') { case 1: break; case 2: break; }",
-      [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
+          warnings: [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
   analyze("switch (1.5) { case 1: break; case 2: break; }",
-      [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
+          warnings: [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
+
+  analyze("switch (null) { case '': break; case 2: break; }",
+          infos: [MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
+                  MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE],
+          errors: [MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL]);
 }
 
 testOperators() {
@@ -160,44 +164,44 @@
     analyze("{ var i = 1 ${op} 2; }");
     analyze("{ var i = 1; i ${op}= 2; }");
     analyze("{ int i; var j = (i = true) ${op} 2; }",
-            [NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
+            warnings: [NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
     analyze("{ int i; var j = 1 ${op} (i = true); }",
-            [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
+            warnings: [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
   }
   for (final op in ['-', '~']) {
     analyze("{ var i = ${op}1; }");
     analyze("{ int i; var j = ${op}(i = true); }",
-        [NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
+            warnings: [NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
   }
   for (final op in ['++', '--']) {
     analyze("{ int i = 1; int j = i${op}; }");
-    analyze("{ int i = 1; bool j = i${op}; }", NOT_ASSIGNABLE);
+    analyze("{ int i = 1; bool j = i${op}; }", warnings: NOT_ASSIGNABLE);
     analyze("{ bool b = true; bool j = b${op}; }",
-        MessageKind.OPERATOR_NOT_FOUND);
+            warnings: MessageKind.OPERATOR_NOT_FOUND);
     analyze("{ bool b = true; int j = ${op}b; }",
-        MessageKind.OPERATOR_NOT_FOUND);
+            warnings: MessageKind.OPERATOR_NOT_FOUND);
   }
   for (final op in ['||', '&&']) {
     analyze("{ bool b = (true ${op} false); }");
-    analyze("{ int b = true ${op} false; }", NOT_ASSIGNABLE);
-    analyze("{ bool b = (1 ${op} false); }", NOT_ASSIGNABLE);
-    analyze("{ bool b = (true ${op} 2); }", NOT_ASSIGNABLE);
+    analyze("{ int b = true ${op} false; }", warnings: NOT_ASSIGNABLE);
+    analyze("{ bool b = (1 ${op} false); }", warnings: NOT_ASSIGNABLE);
+    analyze("{ bool b = (true ${op} 2); }", warnings: NOT_ASSIGNABLE);
   }
   for (final op in ['>', '<', '<=', '>=']) {
     analyze("{ bool b = 1 ${op} 2; }");
-    analyze("{ int i = 1 ${op} 2; }", NOT_ASSIGNABLE);
+    analyze("{ int i = 1 ${op} 2; }", warnings: NOT_ASSIGNABLE);
     analyze("{ int i; bool b = (i = true) ${op} 2; }",
-            [NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
+            warnings: [NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
     analyze("{ int i; bool b = 1 ${op} (i = true); }",
-            [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
+            warnings: [NOT_ASSIGNABLE, NOT_ASSIGNABLE]);
   }
   for (final op in ['==', '!=']) {
     analyze("{ bool b = 1 ${op} 2; }");
-    analyze("{ int i = 1 ${op} 2; }", NOT_ASSIGNABLE);
+    analyze("{ int i = 1 ${op} 2; }", warnings: NOT_ASSIGNABLE);
     analyze("{ int i; bool b = (i = true) ${op} 2; }",
-        NOT_ASSIGNABLE);
+            warnings: NOT_ASSIGNABLE);
     analyze("{ int i; bool b = 1 ${op} (i = true); }",
-        NOT_ASSIGNABLE);
+            warnings: NOT_ASSIGNABLE);
   }
 }
 
@@ -208,14 +212,14 @@
   """);
   // calls to untyped constructor C1
   analyze("new C1(1, 2);");
-  analyze("new C1();", MessageKind.MISSING_ARGUMENT);
-  analyze("new C1(1);", MessageKind.MISSING_ARGUMENT);
-  analyze("new C1(1, 2, 3);", MessageKind.ADDITIONAL_ARGUMENT);
+  analyze("new C1();", warnings: MessageKind.MISSING_ARGUMENT);
+  analyze("new C1(1);", warnings: MessageKind.MISSING_ARGUMENT);
+  analyze("new C1(1, 2, 3);", warnings: MessageKind.ADDITIONAL_ARGUMENT);
   // calls to typed constructor C2
   analyze("new C2(1, 2);");
-  analyze("new C2();", MessageKind.MISSING_ARGUMENT);
-  analyze("new C2(1);", MessageKind.MISSING_ARGUMENT);
-  analyze("new C2(1, 2, 3);", MessageKind.ADDITIONAL_ARGUMENT);
+  analyze("new C2();", warnings: MessageKind.MISSING_ARGUMENT);
+  analyze("new C2(1);", warnings: MessageKind.MISSING_ARGUMENT);
+  analyze("new C2(1, 2, 3);", warnings: MessageKind.ADDITIONAL_ARGUMENT);
 }
 
 void testConstructorInvocationArgumentTypes() {
@@ -232,20 +236,20 @@
   analyze("new C1('string');");
   analyze("new C2(42);");
   analyze("new C2('string');",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("new C3(42);");
   analyze("new C3('string');",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("new C3.named(42);");
   analyze("new C3.named('string');",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
 }
 
 void testMethodInvocationArgumentCount() {
   compiler.parseScript(CLASS_WITH_METHODS);
 
   check(String text, [expectedWarnings]) {
-    analyze("{ ClassWithMethods c; $text }", expectedWarnings);
+    analyze("{ ClassWithMethods c; $text }", warnings: expectedWarnings);
   }
 
   check("c.untypedNoArgumentMethod(1);", MessageKind.ADDITIONAL_ARGUMENT);
@@ -335,7 +339,7 @@
                int localMethod(String str) { return 0; }
                $text
                }
-               """, expectedWarnings);
+               """, warnings: expectedWarnings);
   }
 
   check("int k = c.untypedNoArgumentMethod();");
@@ -467,13 +471,13 @@
   LibraryElement library = mockLibrary(compiler, CLASS_WITH_METHODS);
   compiler.parseScript(CLASS_WITH_METHODS, library);
   ClassElement ClassWithMethods =
-      library.find(const SourceString("ClassWithMethods"));
+      library.find("ClassWithMethods");
   ClassWithMethods.ensureResolved(compiler);
-  Element c = ClassWithMethods.lookupLocalMember(const SourceString('method'));
+  Element c = ClassWithMethods.lookupLocalMember('method');
   assert(c != null);
-  ClassElement SubClass = library.find(const SourceString("SubClass"));
+  ClassElement SubClass = library.find("SubClass");
   SubClass.ensureResolved(compiler);
-  Element d = SubClass.lookupLocalMember(const SourceString('method'));
+  Element d = SubClass.lookupLocalMember('method');
   assert(d != null);
 
   check(Element element, String text, [expectedWarnings]){
@@ -666,7 +670,7 @@
 testNewExpression() {
   compiler.parseScript("class A {}");
   analyze("A a = new A();");
-  analyze("int i = new A();", NOT_ASSIGNABLE);
+  analyze("int i = new A();", warnings: NOT_ASSIGNABLE);
 
 // TODO(karlklose): constructors are not yet implemented.
 //  compiler.parseScript(
@@ -702,17 +706,17 @@
 testConditionalExpression() {
   analyze("int i = true ? 2 : 1;");
   analyze("int i = true ? 'hest' : 1;");
-  analyze("int i = true ? 'hest' : 'fisk';", NOT_ASSIGNABLE);
+  analyze("int i = true ? 'hest' : 'fisk';", warnings: NOT_ASSIGNABLE);
   analyze("String s = true ? 'hest' : 'fisk';");
 
   analyze("true ? 1 : 2;");
   analyze("null ? 1 : 2;");
-  analyze("0 ? 1 : 2;", NOT_ASSIGNABLE);
-  analyze("'' ? 1 : 2;", NOT_ASSIGNABLE);
+  analyze("0 ? 1 : 2;", warnings: NOT_ASSIGNABLE);
+  analyze("'' ? 1 : 2;", warnings: NOT_ASSIGNABLE);
   analyze("{ int i; true ? i = 2.7 : 2; }",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("{ int i; true ? 2 : i = 2.7; }",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("{ int i; i = true ? 2.7 : 2; }");
 }
 
@@ -720,13 +724,13 @@
   analyze("if (true) {}");
   analyze("if (null) {}");
   analyze("if (0) {}",
-  NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("if ('') {}",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("{ int i = 27; if (true) { i = 2.7; } else {} }",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
   analyze("{ int i = 27; if (true) {} else { i = 2.7; } }",
-          NOT_ASSIGNABLE);
+          warnings: NOT_ASSIGNABLE);
 }
 
 testThis() {
@@ -735,9 +739,9 @@
                      }""";
   LibraryElement library = mockLibrary(compiler, script);
   compiler.parseScript(script, library);
-  ClassElement foo = library.find(const SourceString("Foo"));
+  ClassElement foo = library.find("Foo");
   foo.ensureResolved(compiler);
-  Element method = foo.lookupLocalMember(const SourceString('method'));
+  Element method = foo.lookupLocalMember('method');
   analyzeIn(method, "{ int i = this; }", NOT_ASSIGNABLE);
   analyzeIn(method, "{ Object o = this; }");
   analyzeIn(method, "{ Foo f = this; }");
@@ -756,9 +760,9 @@
     ''';
   LibraryElement library = mockLibrary(compiler, script);
   compiler.parseScript(script, library);
-  ClassElement B = library.find(const SourceString("B"));
+  ClassElement B = library.find("B");
   B.ensureResolved(compiler);
-  Element method = B.lookupLocalMember(const SourceString('method'));
+  Element method = B.lookupLocalMember('method');
   analyzeIn(method, "{ int i = super.field; }", NOT_ASSIGNABLE);
   analyzeIn(method, "{ Object o = super.field; }");
   analyzeIn(method, "{ String s = super.field; }");
@@ -830,7 +834,7 @@
       """;
 
   check(String text, [expectedWarnings]) {
-    analyze('$header $text }', expectedWarnings);
+    analyze('$header $text }', warnings: expectedWarnings);
   }
 
   // Positive tests on operators.
@@ -1057,9 +1061,9 @@
                      }""";
   LibraryElement library = mockLibrary(compiler, script);
   compiler.parseScript(script, library);
-  ClassElement foo = library.find(const SourceString("Foo"));
+  ClassElement foo = library.find("Foo");
   foo.ensureResolved(compiler);
-  Element method = foo.lookupLocalMember(const SourceString('method'));
+  Element method = foo.lookupLocalMember('method');
 
   analyzeIn(method, "{ Type type = T; }");
   analyzeIn(method, "{ T type = T; }", NOT_ASSIGNABLE);
@@ -1090,10 +1094,10 @@
 
   LibraryElement library = mockLibrary(compiler, script);
   compiler.parseScript(script, library);
-  ClassElement classTest = library.find(const SourceString("Test"));
+  ClassElement classTest = library.find("Test");
   classTest.ensureResolved(compiler);
   FunctionElement methodTest =
-    classTest.lookupLocalMember(const SourceString("test"));
+    classTest.lookupLocalMember("test");
 
   test(String expression, [message]) {
     analyzeIn(methodTest, "{ $expression; }", message);
@@ -1132,10 +1136,10 @@
 
   LibraryElement library = mockLibrary(compiler, script);
   compiler.parseScript(script, library);
-  ClassElement classTest = library.find(const SourceString("Test"));
+  ClassElement classTest = library.find("Test");
   classTest.ensureResolved(compiler);
   FunctionElement methodTest =
-    classTest.lookupLocalMember(const SourceString("test"));
+    classTest.lookupLocalMember("test");
 
   test(String expression, [message]) {
     analyzeIn(methodTest, "{ $expression; }", message);
@@ -1156,10 +1160,10 @@
 
   LibraryElement library = mockLibrary(compiler, script);
   compiler.parseScript(script, library);
-  ClassElement classTest = library.find(const SourceString("Test"));
+  ClassElement classTest = library.find("Test");
   classTest.ensureResolved(compiler);
   FunctionElement methodTest =
-    classTest.lookupLocalMember(const SourceString("test"));
+    classTest.lookupLocalMember("test");
 
   test(String expression, [message]) {
     analyzeIn(methodTest, "{ $expression; }", message);
@@ -1175,16 +1179,16 @@
 void testFunctionTypeLookup() {
   analyze('(int f(int)) => f.toString;');
   analyze('(int f(int)) => f.toString();');
-  analyze('(int f(int)) => f.foo;', MEMBER_NOT_FOUND);
-  analyze('(int f(int)) => f.foo();', MessageKind.METHOD_NOT_FOUND);
+  analyze('(int f(int)) => f.foo;', warnings: MEMBER_NOT_FOUND);
+  analyze('(int f(int)) => f.foo();', warnings: MessageKind.METHOD_NOT_FOUND);
 }
 
 void testTypedefLookup() {
   compiler.parseScript("typedef int F(int);");
   analyze('(F f) => f.toString;');
   analyze('(F f) => f.toString();');
-  analyze('(F f) => f.foo;', MEMBER_NOT_FOUND);
-  analyze('(F f) => f.foo();', MessageKind.METHOD_NOT_FOUND);
+  analyze('(F f) => f.foo;', warnings: MEMBER_NOT_FOUND);
+  analyze('(F f) => f.foo();', warnings: MessageKind.METHOD_NOT_FOUND);
 }
 
 void testTypeLiteral() {
@@ -1196,27 +1200,27 @@
 
   // Check direct access.
   analyze('Type m() => int;');
-  analyze('int m() => int;', NOT_ASSIGNABLE);
+  analyze('int m() => int;', warnings: NOT_ASSIGNABLE);
 
   // Check access in assignment.
   analyze('m(Type val) => val = Class;');
-  analyze('m(int val) => val = Class;', NOT_ASSIGNABLE);
+  analyze('m(int val) => val = Class;', warnings: NOT_ASSIGNABLE);
 
   // Check access as argument.
   analyze('m(Type val) => m(int);');
-  analyze('m(int val) => m(int);', NOT_ASSIGNABLE);
+  analyze('m(int val) => m(int);', warnings: NOT_ASSIGNABLE);
 
   // Check access as argument in member access.
   analyze('m(Type val) => m(int).foo;');
-  analyze('m(int val) => m(int).foo;', NOT_ASSIGNABLE);
+  analyze('m(int val) => m(int).foo;', warnings: NOT_ASSIGNABLE);
 
   // Check static property access.
   analyze('m() => Class.field;');
-  analyze('m() => (Class).field;', MEMBER_NOT_FOUND);
+  analyze('m() => (Class).field;', warnings: MEMBER_NOT_FOUND);
 
   // Check static method access.
   analyze('m() => Class.method();');
-  analyze('m() => (Class).method();', MessageKind.METHOD_NOT_FOUND);
+  analyze('m() => (Class).method();', warnings: MessageKind.METHOD_NOT_FOUND);
 }
 
 void testInitializers() {
@@ -1435,7 +1439,7 @@
                            ''');
 
   check(String text, [expectedWarnings]) {
-    analyze('{ $text }', expectedWarnings);
+    analyze('{ $text }', warnings: expectedWarnings);
   }
 
   check("variable = '';");
@@ -1502,6 +1506,139 @@
   check("sc.setterField = 0;");
 }
 
+testTypePromotionHints() {
+  compiler.parseScript(r'''class A {
+                             var a = "a";
+                           }
+                           class B extends A {
+                             var b = "b";
+                           }
+                           class C {
+                             var c = "c";
+                           }
+                           class D<T> {
+                             T d;
+                           }
+                           class E<T> extends D<T> {
+                             T e;
+                           }
+                           ''');
+
+  check(String text, {warnings, hints, infos}) {
+    analyze('{ $text }', warnings: warnings, hints: hints, infos: infos);
+  }
+
+  check(r'''
+            A a = new B();
+            if (a is C) {
+              var x = a.c;
+            }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [MessageKind.NOT_MORE_SPECIFIC],
+        infos: []);
+
+  check(r'''
+            A a = new B();
+            if (a is C) {
+              var x = '${a.c}${a.c}';
+            }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning,
+                   MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [MessageKind.NOT_MORE_SPECIFIC],
+        infos: []);
+
+  check(r'''
+            A a = new B();
+            if (a is C) {
+              var x = '${a.d}${a.d}'; // Type promotion wouldn't help.
+            }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning,
+                   MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [],
+        infos: []);
+
+  check('''
+           D d = new E();
+           if (d is E<int>) {
+             var x = d.e;
+           }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [MessageKind.NOT_MORE_SPECIFIC_RAW],
+        infos: []);
+
+  check('''
+           D d = new E();
+           if (d is E<int>) {
+             var x = d.f; // Type promotion wouldn't help.
+           }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [],
+        infos: []);
+
+  check('''
+           A a = new B();
+           if (a is B) {
+             a = null;
+             var x = a.b;
+           }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [MessageKind.POTENTIAL_MUTATION],
+        infos: [MessageKind.POTENTIAL_MUTATION_HERE]);
+
+  check('''
+           A a = new B();
+           if (a is B) {
+             a = null;
+             var x = a.c; // Type promotion wouldn't help.
+           }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [],
+        infos: []);
+
+  check('''
+           A a = new B();
+           local() { a = new A(); }
+           if (a is B) {
+             var x = a.b;
+           }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [MessageKind.POTENTIAL_MUTATION_IN_CLOSURE],
+        infos: [MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE]);
+
+  check('''
+           A a = new B();
+           local() { a = new A(); }
+           if (a is B) {
+             var x = a.c; // Type promotion wouldn't help.
+           }''',
+        warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+        hints: [],
+        infos: []);
+
+  check('''
+           A a = new B();
+           if (a is B) {
+             var x = () => a;
+             var y = a.b;
+           }
+           a = new A();''',
+      warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+      hints: [MessageKind.ACCESSED_IN_CLOSURE],
+      infos: [MessageKind.ACCESSED_IN_CLOSURE_HERE,
+              MessageKind.POTENTIAL_MUTATION_HERE]);
+
+  check('''
+           A a = new B();
+           if (a is B) {
+             var x = () => a;
+             var y = a.c; // Type promotion wouldn't help.
+           }
+           a = new A();''',
+      warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
+      hints: [],
+      infos: []);
+}
+
 const CLASS_WITH_METHODS = '''
 class ClassWithMethods {
   untypedNoArgumentMethod() {}
@@ -1642,18 +1779,24 @@
   // Type check last class declaration or member.
   TypeCheckerVisitor checker =
       new TypeCheckerVisitor(compiler, mapping, types);
-  compiler.clearWarnings();
+  compiler.clearMessages();
   checker.analyze(node);
   compareWarningKinds(text, expectedWarnings, compiler.warnings);
 
   compiler.diagnosticHandler = null;
 }
 
-analyze(String text, [expectedWarnings, expectedErrors]) {
-  if (expectedWarnings == null) expectedWarnings = [];
-  if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
-  if (expectedErrors == null) expectedErrors = [];
-  if (expectedErrors is !List) expectedErrors = [expectedErrors];
+/**
+ * Analyze the statement [text] and check messages from the type checker.
+ * [errors] and [warnings] can be either [:null:], a single [MessageKind] or
+ * a list of [MessageKind]s. If [hints] and [infos] are [:null:] the
+ * corresponding message kinds are ignored.
+ */
+analyze(String text, {errors, warnings, List hints, List infos}) {
+  if (warnings == null) warnings = [];
+  if (warnings is !List) warnings = [warnings];
+  if (errors == null) errors = [];
+  if (errors is !List) errors = [errors];
 
   compiler.diagnosticHandler = createHandler(compiler, text);
 
@@ -1665,15 +1808,16 @@
   Element compilationUnit =
     new CompilationUnitElementX(new Script(null, null), compiler.mainApp);
   Element function = new ElementX(
-      buildSourceString(''), ElementKind.FUNCTION, compilationUnit);
+      '', ElementKind.FUNCTION, compilationUnit);
   TreeElements elements = compiler.resolveNodeStatement(node, function);
   TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
                                                                 types);
-  compiler.clearWarnings();
-  compiler.clearErrors();
+  compiler.clearMessages();
   checker.analyze(node);
-  compareWarningKinds(text, expectedWarnings, compiler.warnings);
-  compareWarningKinds(text, expectedErrors, compiler.errors);
+  compareWarningKinds(text, warnings, compiler.warnings);
+  compareWarningKinds(text, errors, compiler.errors);
+  if (hints != null) compareWarningKinds(text, hints, compiler.hints);
+  if (infos != null) compareWarningKinds(text, infos, compiler.infos);
   compiler.diagnosticHandler = null;
 }
 
@@ -1682,8 +1826,8 @@
     var beginToken = message.node.getBeginToken();
     var endToken = message.node.getEndToken();
     int begin = beginToken.charOffset;
-    int end = endToken.charOffset + endToken.slowCharCount;
-    SourceFile sourceFile = new SourceFile('analysis', text);
+    int end = endToken.charOffset + endToken.charCount;
+    SourceFile sourceFile = new StringSourceFile('analysis', text);
     print(sourceFile.getLocationMessage(message.message.toString(),
                                         begin, end, true, (str) => str));
   }
@@ -1701,7 +1845,7 @@
   TreeElements elements = compiler.resolveNodeStatement(node, element);
   TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
                                                                 types);
-  compiler.clearWarnings();
+  compiler.clearMessages();
   checker.analyze(node);
   generateOutput(text);
   compareWarningKinds(text, expectedWarnings, compiler.warnings);
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index 8947932..fd7cbf4 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -687,7 +687,7 @@
 
   // Grab hold of a supertype for String so we can produce potential
   // string types.
-  patternClass = compiler.coreLibrary.find(buildSourceString('Pattern'));
+  patternClass = compiler.coreLibrary.find('Pattern');
 
   nonPrimitive1 = new HType.nonNullSubtype(
       compiler.mapClass, compiler);
diff --git a/tests/compiler/dart2js/type_equals_test.dart b/tests/compiler/dart2js/type_equals_test.dart
index 4997583..2bb732e 100644
--- a/tests/compiler/dart2js/type_equals_test.dart
+++ b/tests/compiler/dart2js/type_equals_test.dart
@@ -12,8 +12,8 @@
   Expect.isTrue((expect != null), 'required parameter "expect" not given');
   var clazz = findElement(compiler, "Class");
   clazz.ensureResolved(compiler);
-  var element1 = clazz.buildScope().lookup(buildSourceString(name1));
-  var element2 = clazz.buildScope().lookup(buildSourceString(name2));
+  var element1 = clazz.buildScope().lookup(name1);
+  var element2 = clazz.buildScope().lookup(name2);
   Expect.isNotNull(element1);
   Expect.isNotNull(element2);
   Expect.equals(element1.kind, ElementKind.FUNCTION);
diff --git a/tests/compiler/dart2js/type_promotion_test.dart b/tests/compiler/dart2js/type_promotion_test.dart
index 37f77c9..b7b7cf0 100644
--- a/tests/compiler/dart2js/type_promotion_test.dart
+++ b/tests/compiler/dart2js/type_promotion_test.dart
@@ -14,6 +14,7 @@
 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';

 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';

 import '../../../sdk/lib/_internal/compiler/implementation/util/uri_extras.dart';

+import 'dart:convert';

 

 const List<String> TESTS = const [

     'language/type_promotion_assign_test.dart',

@@ -32,8 +33,8 @@
   bool warningsMismatch = false;

   Future.forEach(TESTS, (String test) {

     Uri uri = script.resolve('../../$test');

-    String source = readAll(uriPathToNative(uri.path));

-    SourceFile file = new SourceFile(

+    String source = UTF8.decode(readAll(uriPathToNative(uri.path)));

+    SourceFile file = new StringSourceFile(

         relativize(currentDirectory, uri, isWindows), source);

     Map<int,String> expectedWarnings = {};

     int lineNo = 0;

diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart
index e222971..482c03a 100644
--- a/tests/compiler/dart2js/type_representation_test.dart
+++ b/tests/compiler/dart2js/type_representation_test.dart
@@ -37,7 +37,7 @@
         new TypeRepresentationGenerator(env.compiler);
 
     Expression onVariable(TypeVariableType variable) {
-      return new VariableUse(variable.name.slowToString());
+      return new VariableUse(variable.name);
     }
 
     String stringify(Expression expression) {
diff --git a/tests/compiler/dart2js/type_substitution_test.dart b/tests/compiler/dart2js/type_substitution_test.dart
index 483e506..15934bd 100644
--- a/tests/compiler/dart2js/type_substitution_test.dart
+++ b/tests/compiler/dart2js/type_substitution_test.dart
@@ -14,7 +14,7 @@
 DartType getType(compiler, String name) {
   var clazz = findElement(compiler, "Class");
   clazz.ensureResolved(compiler);
-  var element = clazz.buildScope().lookup(buildSourceString(name));
+  var element = clazz.buildScope().lookup(name);
   Expect.isNotNull(element);
   Expect.equals(element.kind, ElementKind.FUNCTION);
   FunctionSignature signature = element.computeSignature(compiler);
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index 641a07a..7f2a8fd 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import "package:expect/expect.dart";
 import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
-import "parser_helper.dart" show SourceString;
 import "compiler_helper.dart";
 
 GenericType instantiate(TypeDeclarationElement element,
@@ -60,7 +59,7 @@
   }
 
   DartType getMemberType(ClassElement element, String name) {
-    Element member = element.localLookup(sourceString(name));
+    Element member = element.localLookup(name);
     return member.computeType(compiler);
   }
 
@@ -72,8 +71,6 @@
     return compiler.types.isMoreSpecific(T, S);
   }
 
-  SourceString sourceString(String name) => new SourceString(name);
-
   FunctionType functionType(DartType returnType,
                             List<DartType> parameters,
                             {List<DartType> optionalParameter,
@@ -83,11 +80,11 @@
     Link<DartType> optionalParameterTypes = optionalParameter != null
         ? new Link<DartType>.fromList(optionalParameter)
         : const Link<DartType>();
-    var namedParameterNames = new LinkBuilder<SourceString>();
+    var namedParameterNames = new LinkBuilder<String>();
     var namedParameterTypes = new LinkBuilder<DartType>();
     if (namedParameters != null) {
       namedParameters.forEach((String name, DartType type) {
-        namedParameterNames.addLast(sourceString(name));
+        namedParameterNames.addLast(name);
         namedParameterTypes.addLast(type);
       });
     }
diff --git a/tests/compiler/dart2js/unparser2_test.dart b/tests/compiler/dart2js/unparser2_test.dart
index e2eb006..cd0d458 100644
--- a/tests/compiler/dart2js/unparser2_test.dart
+++ b/tests/compiler/dart2js/unparser2_test.dart
@@ -60,7 +60,7 @@
   Script script = new Script(null, null);
   LibraryElement lib = new LibraryElementX(script);
   CompilationUnitElement element = new CompilationUnitElementX(script, lib);
-  StringScanner scanner = new StringScanner(source);
+  StringScanner scanner = new StringScanner.fromString(source);
   Token beginToken = scanner.tokenize();
   NodeListener listener = new NodeListener(diagnosticListener, element);
   Parser parser = new Parser(listener);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 5c1351e..c475d9b 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -14,6 +14,12 @@
 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).
+
+[ $compiler == none && $runtime == dartium ]
+main_test: Fail  # Dartium needs to check for both main() and main(args).
+
 [ $runtime == ff || $runtime == ie9 || $runtime == jsshell ]
 unicode_test: Fail
 
@@ -35,6 +41,7 @@
 [ $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.
@@ -58,7 +65,7 @@
 [ $compiler == dart2dart ]
 compare_to2_test: Fail # inherited from VM
 unicode_test: Fail # inherited from VM
-
+main_test: Fail # dart2dart needs to check for both main() and main(args).
 
 # Library changes
 [ $compiler == none || $compiler == dart2js || $compiler == dart2dart ]
diff --git a/tests/corelib/main_test.dart b/tests/corelib/main_test.dart
new file mode 100644
index 0000000..14128119
--- /dev/null
+++ b/tests/corelib/main_test.dart
@@ -0,0 +1,10 @@
+// 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 main_test;
+import "package:expect/expect.dart";
+
+main(List<String> args) {
+  Expect.equals(0, args.length);
+}
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index b0246f0..b59d746 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -17,15 +17,19 @@
   Set set = create();
 
   testLength(0, set);
-  set.add(1);
+  Expect.isTrue(set.add(1));
   testLength(1, set);
   Expect.isTrue(set.contains(1));
 
-  set.add(1);
+  Expect.isFalse(set.add(1));
   testLength(1, set);
   Expect.isTrue(set.contains(1));
 
-  set.remove(1);
+  Expect.isTrue(set.remove(1));
+  testLength(0, set);
+  Expect.isFalse(set.contains(1));
+
+  Expect.isFalse(set.remove(1));
   testLength(0, set);
   Expect.isFalse(set.contains(1));
 
@@ -184,7 +188,7 @@
   // Test Set.clear.
   set.clear();
   testLength(0, set);
-  set.add(11);
+  Expect.isTrue(set.add(11));
   testLength(1, set);
 }
 
@@ -205,8 +209,8 @@
   testLength(8, set);
   set.removeAll(strings.where((x) => x.length == 3));
   testLength(4, set);
-  set.add("bar");
-  set.add("qux");
+  Expect.isTrue(set.add("bar"));
+  Expect.isTrue(set.add("qux"));
   testLength(6, set);
   set.addAll(strings);
   testLength(8, set);
diff --git a/tests/html/custom/document_register_type_extensions_test.dart b/tests/html/custom/document_register_type_extensions_test.dart
index 5acba99..10b06ef 100644
--- a/tests/html/custom/document_register_type_extensions_test.dart
+++ b/tests/html/custom/document_register_type_extensions_test.dart
@@ -45,6 +45,26 @@
   FooBad.created() : super.created();
 }
 
+class MyCanvas extends CanvasElement {
+  static const tag = 'my-canvas';
+  factory MyCanvas() => new Element.tag('canvas', tag);
+
+  MyCanvas.created() : super.created();
+
+  void fillAsRed() {
+    width = 100;
+    height = 100;
+
+    var context = this.getContext('2d');
+    context.fillStyle = 'red';
+    context.fillRect(0, 0, width, height);
+    context.fill();
+
+    var data = context.getImageData(0, 0, 1, 1).data;
+    expect(data, [255, 0, 0, 255]);
+  }
+}
+
 main() {
   useHtmlIndividualConfiguration();
 
@@ -68,6 +88,7 @@
     document.register(Bar.tag, Bar, extendsTag: 'input');
     document.register(Baz.tag, Baz);
     document.register(Qux.tag, Qux, extendsTag: 'input');
+    document.register(MyCanvas.tag, MyCanvas, extendsTag: 'canvas');
   }
 
   setUp(loadPolyfills);
@@ -267,4 +288,13 @@
       expect(divBarParsed is DivElement, isTrue);
     });
   });
+
+  group('functional', () {
+    setUp(registerTypes);
+
+    test('canvas', () {
+      var canvas = new MyCanvas();
+      canvas.fillAsRed();
+    });
+  });
 }
diff --git a/tests/html/custom/entered_left_view_test.dart b/tests/html/custom/entered_left_view_test.dart
index deff709..f30b794 100644
--- a/tests/html/custom/entered_left_view_test.dart
+++ b/tests/html/custom/entered_left_view_test.dart
@@ -111,7 +111,7 @@
 
     test('Created, owned by a document without a view', () {
       a = docB.createElement('x-a');
-      expect(a.document, docB,
+      expect(a.ownerDocument, docB,
           reason:'new instance should be owned by the document the definition '
           'was registered with');
       expect(invocations, ['created'],
diff --git a/tests/html/element_classes_test.dart b/tests/html/element_classes_test.dart
index f4ed7a4..9ef9860 100644
--- a/tests/html/element_classes_test.dart
+++ b/tests/html/element_classes_test.dart
@@ -107,10 +107,12 @@
 
   test('add', () {
     final classes = makeClassSet();
-    classes.add('qux');
+    var added = classes.add('qux');
+    expect(added, isTrue);
     expect(classes, orderedEquals(['foo', 'bar', 'baz', 'qux']));
 
-    classes.add('qux');
+    added = classes.add('qux');
+    expect(added, isFalse);
     final list = new List.from(classes);
     list.sort((a, b) => a.compareTo(b));
     expect(list, orderedEquals(['bar', 'baz', 'foo', 'qux']),
@@ -235,7 +237,9 @@
 
   test('listAdd', () {
     var elements =  listElementSetup();
-    elements.classes.add('lassie');
+    var added = elements.classes.add('lassie');
+    expect(added, isNull);
+
     expect(elements.classes,
         unorderedEquals(['lassie', 'qux', 'quux', 'meta', 'classy', 'lassy']));
     for (Element e in elements) {
diff --git a/tests/html/element_test.dart b/tests/html/element_test.dart
index 06b1e41..43d0bc5 100644
--- a/tests/html/element_test.dart
+++ b/tests/html/element_test.dart
@@ -220,6 +220,16 @@
       expect(node.parent, isNull);
       expect(node.innerHtml, 'foobar');
     });
+
+    test('.html can fire events', () {
+      var e = new Element.html('<button>aha</button>');
+      var gotEvent = false;
+      e.onClick.listen((_) {
+        gotEvent = true;
+      });
+      e.click();
+      expect(gotEvent, isTrue, reason: 'click should have raised click event');
+    });
   });
 
   group('eventListening', () {
@@ -849,6 +859,43 @@
       query('.i').click();
       expect(firedEvent5, true);
     });
+
+    test('event ordering', () {
+      var a = new DivElement();
+      var b = new DivElement();
+      a.append(b);
+      var c = new DivElement();
+      b.append(c);
+
+      var eventOrder = [];
+
+      a.on['custom_event'].listen((_) {
+        eventOrder.add('a no-capture');
+      });
+
+      a.on['custom_event'].capture((_) {
+        eventOrder.add('a capture');
+      });
+
+      b.on['custom_event'].listen((_) {
+        eventOrder.add('b no-capture');
+      });
+
+      b.on['custom_event'].capture((_) {
+        eventOrder.add('b capture');
+      });
+
+      document.body.append(a);
+
+      var event = new Event('custom_event', canBubble: true);
+      c.dispatchEvent(event);
+      expect(eventOrder, [
+        'a capture',
+        'b capture',
+        'b no-capture',
+        'a no-capture'
+      ]);
+    });
   });
 
   group('ElementList', () {
diff --git a/tests/html/html.status b/tests/html/html.status
index 05f0770..d3d7586 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -68,6 +68,7 @@
 
 [ $compiler == dart2js && ( $runtime == ie9 || $runtime == ie10 ) ]
 worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
+js_test: Fail # Issue 14246
 
 [ $compiler == dart2js && $runtime == safari ]
 url_test: Fail # Issue 10096
@@ -167,6 +168,7 @@
 custom/document_register_type_extensions_test/construction: Fail # Issue 13193
 
 [ $runtime == ie9 ]
+event_customevent_test: Fail # Issue 14170
 isolates_test: Timeout # Issue 13027
 blob_constructor_test: Fail
 custom/document_register_type_extensions_test/namespaces: Fail # Issue 13193
diff --git a/tests/html/indexeddb_1_test.dart b/tests/html/indexeddb_1_test.dart
index c57f8d1..a099bf0 100644
--- a/tests/html/indexeddb_1_test.dart
+++ b/tests/html/indexeddb_1_test.dart
@@ -3,6 +3,7 @@
 import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:async';
 import 'dart:html' as html;
+import 'dart:math' as math;
 import 'dart:indexed_db' as idb;
 
 const String STORE_NAME = 'TEST';
@@ -37,7 +38,8 @@
 }
 
 testReadWrite(key, value, matcher,
-    [dbName, storeName = STORE_NAME, version = VERSION]) => () {
+    [dbName, storeName = STORE_NAME, version = VERSION,
+    stringifyResult = false]) => () {
   if (dbName == null) {
     dbName = nextDatabaseName();
   }
@@ -60,7 +62,13 @@
       return transaction.objectStore(storeName).getObject(key);
     }).then((object) {
       db.close();
-      expect(object, matcher);
+      if (stringifyResult) {
+        // Stringify the numbers to verify that we're correctly returning ints
+        // as ints vs doubles.
+        expect(object.toString(), matcher);
+      } else {
+        expect(object, matcher);
+      }
     }).whenComplete(() {
       if (db != null) {
         db.close();
@@ -70,7 +78,8 @@
 };
 
 testReadWriteTyped(key, value, matcher,
-    [dbName, storeName = STORE_NAME, version = VERSION]) => () {
+    [dbName, storeName = STORE_NAME, version = VERSION,
+    stringifyResult = false]) => () {
   if (dbName == null) {
     dbName = nextDatabaseName();
   }
@@ -95,7 +104,13 @@
       return transaction.objectStore(storeName).getObject(key);
     }).then((object) {
       db.close();
-      expect(object, matcher);
+      if (stringifyResult) {
+        // Stringify the numbers to verify that we're correctly returning ints
+        // as ints vs doubles.
+        expect(object.toString(), matcher);
+      } else {
+        expect(object, matcher);
+      }
     }).whenComplete(() {
       if (db != null) {
         db.close();
@@ -110,6 +125,12 @@
   test('List', testFunction(123, [1, 2, 3], equals([1, 2, 3])));
   test('List 2', testFunction(123, [2, 3, 4], equals([2, 3, 4])));
   test('bool', testFunction(123, [true, false], equals([true, false])));
+  test('largeInt', testFunction(123, 1371854424211,
+      equals("1371854424211"), null, STORE_NAME, VERSION, true));
+  test('largeDoubleConvertedToInt', testFunction(123, 1371854424211.0,
+      equals("1371854424211"), null, STORE_NAME, VERSION, true));
+  test('largeIntInMap', testFunction(123, {'time': 4503599627370492},
+      equals("{time: 4503599627370492}"), null, STORE_NAME, VERSION, true));
   var now = new DateTime.now();
   test('DateTime', testFunction(123, now,
     predicate((date) =>
diff --git a/tests/html/js_test.dart b/tests/html/js_test.dart
index 7a0abbb..e120895 100644
--- a/tests/html/js_test.dart
+++ b/tests/html/js_test.dart
@@ -6,6 +6,8 @@
 
 import 'dart:async';
 import 'dart:html';
+import 'dart:typed_data' show ByteBuffer, Int32List;
+import 'dart:indexed_db' show IdbFactory, KeyRange;
 import 'dart:js';
 
 import '../../pkg/unittest/lib/unittest.dart';
@@ -33,6 +35,10 @@
   return x;
 }
 
+function returnThis() {
+  return this;
+}
+
 function getTypeOf(o) {
   return typeof(o);
 }
@@ -97,15 +103,50 @@
   return result;
 }
 
+function getNewDate() {
+  return new Date(1995, 11, 17);
+}
+
 function getNewDivElement() {
   return document.createElement("div");
 }
 
+function getNewBlob() {
+  var fileParts = ['<a id="a"><b id="b">hey!</b></a>'];
+  return new Blob(fileParts, {type : 'text/html'});
+}
+
+function getNewIDBKeyRange() {
+  return IDBKeyRange.only(1);
+}
+
+function getNewImageData() {
+  var canvas = document.createElement('canvas');
+  var context = canvas.getContext('2d');
+  return context.createImageData(1, 1);
+}
+
+function getNewInt32Array() {
+  return new Int32Array([1, 2, 3, 4, 5, 6, 7, 8]);
+}
+
+function getNewArrayBuffer() {
+  return new ArrayBuffer(8);
+}
+
+function isPropertyInstanceOf(property, type) {
+  return window[property] instanceof type;
+}
+
 function testJsMap(callback) {
   var result = callback();
   return result['value'];
 }
 
+function addTestProperty(o) {
+  o.testProperty = "test";
+}
+
 function Bar() {
   return "ret_value";
 }
@@ -125,14 +166,21 @@
   this.f11 = p11;
 }
 
+function Liar(){}
+
+Liar.prototype.toString = function() {
+  return 1;
+}
+
 function identical(o1, o2) {
   return o1 === o2;
 }
+
 """;
   document.body.append(script);
 }
 
-class Foo implements Serializable<JsObject> {
+class Foo {
   final JsObject _proxy;
 
   Foo(num a) : this._proxy = new JsObject(context['Foo'], [a]);
@@ -143,7 +191,7 @@
   num bar() => _proxy.callMethod('bar');
 }
 
-class Color implements Serializable<String> {
+class Color {
   static final RED = new Color._("red");
   static final BLUE = new Color._("blue");
   String _value;
@@ -165,17 +213,15 @@
       expect(identical(c1, c2), isTrue);
     });
 
+  /*
+    TODO(jacobr): enable this test when dartium supports maintaining proxy
+    equality.
+
     test('identical JS objects should have identical proxies', () {
       var o1 = new JsObject(context['Foo'], [1]);
       context['f1'] = o1;
       var o2 = context['f1'];
-      expect(identical(o1, o2), isTrue);
-    });
-
-    test('identical JS functions should have identical proxies', () {
-      var f1 = context['Object'];
-      var f2 = context['Object'];
-      expect(identical(f1, f2), isTrue);
+      expect(equals(o1, o2), isTrue);
     });
 
     test('identical Dart objects should have identical proxies', () {
@@ -187,6 +233,15 @@
       var f1 = () => print("I'm a Function!");
       expect(context.callMethod('identical', [f1, f1]), isTrue);
     });
+    */
+
+    // TODO(jacobr): switch from equals to indentical when dartium supports
+    // maintaining proxy equality.
+    test('identical JS functions should have equal proxies', () {
+      var f1 = context['Object'];
+      var f2 = context['Object'];
+      expect(f1, equals(f2));
+    });
 
     // TODO(justinfagnani): old tests duplicate checks above, remove
     // on test next cleanup pass
@@ -196,214 +251,288 @@
       context['foo1'] = foo1;
       context['foo2'] = foo2;
       expect(foo1, isNot(equals(context['foo2'])));
-      expect(foo2, same(context['foo2']));
+      expect(foo2, equals(context['foo2']));
       context.deleteProperty('foo1');
       context.deleteProperty('foo2');
     });
 
+
     test('retrieve same dart Object', () {
-      final date = new DateTime.now();
-      context['dartDate'] = date;
-      expect(context['dartDate'], same(date));
-      context.deleteProperty('dartDate');
+      final obj = new Object();
+      context['obj'] = obj;
+      expect(context['obj'], same(obj));
+      context.deleteProperty('obj');
     });
 
   });
 
-  test('read global field', () {
-    expect(context['x'], equals(42));
-    expect(context['y'], isNull);
+  group('context', () {
+
+    test('read global field', () {
+      expect(context['x'], equals(42));
+      expect(context['y'], isNull);
+    });
+
+    test('read global field with underscore', () {
+      expect(context['_x'], equals(123));
+      expect(context['y'], isNull);
+    });
+
+    test('write global field', () {
+      context['y'] = 42;
+      expect(context['y'], equals(42));
+    });
+
   });
 
-  test('read global field with underscore', () {
-    expect(context['_x'], equals(123));
-    expect(context['y'], isNull);
-  });
+  group('new JsObject()', () {
 
-  test('hashCode and operator==(other)', () {
-    final o1 = context['Object'];
-    final o2 = context['Object'];
-    expect(o1 == o2, isTrue);
-    expect(o1.hashCode == o2.hashCode, isTrue);
-    final d = context['document'];
-    expect(o1 == d, isFalse);
-  });
+    test('new Foo()', () {
+      var foo = new JsObject(context['Foo'], [42]);
+      expect(foo['a'], equals(42));
+      expect(foo.callMethod('bar'), equals(42));
+      expect(() => foo.callMethod('baz'), throwsA(isNoSuchMethodError));
+    });
 
-  test('js instantiation : new Foo()', () {
-    final Foo2 = context['container']['Foo'];
-    final foo = new JsObject(Foo2, [42]);
-    expect(foo['a'], 42);
-    expect(Foo2['b'], 38);
-  });
+    test('new container.Foo()', () {
+      final Foo2 = context['container']['Foo'];
+      final foo = new JsObject(Foo2, [42]);
+      expect(foo['a'], 42);
+      expect(Foo2['b'], 38);
+    });
 
-  test('js instantiation : new Array()', () {
-    final a = new JsObject(context['Array']);
-    expect(a, isNotNull);
-    expect(a['length'], equals(0));
+    test('new Array()', () {
+      final a = new JsObject(context['Array']);
+      expect(a, isNotNull);
+      expect(a['length'], equals(0));
 
-    a.callMethod('push', ["value 1"]);
-    expect(a['length'], equals(1));
-    expect(a[0], equals("value 1"));
+      a.callMethod('push', ["value 1"]);
+      expect(a['length'], equals(1));
+      expect(a[0], equals("value 1"));
 
-    a.callMethod('pop');
-    expect(a['length'], equals(0));
-  });
+      a.callMethod('pop');
+      expect(a['length'], equals(0));
+    });
 
-  test('js instantiation : new Date()', () {
-    final a = new JsObject(context['Date']);
-    expect(a.callMethod('getTime'), isNotNull);
-  });
+    test('new Date()', () {
+      final a = new JsObject(context['Date']);
+      expect(a.callMethod('getTime'), isNotNull);
+    });
 
-  test('js instantiation : new Date(12345678)', () {
-    final a = new JsObject(context['Date'], [12345678]);
-    expect(a.callMethod('getTime'), equals(12345678));
-  });
+    test('new Date(12345678)', () {
+      final a = new JsObject(context['Date'], [12345678]);
+      expect(a.callMethod('getTime'), equals(12345678));
+    });
 
-  test('js instantiation : new Date("December 17, 1995 03:24:00 GMT")',
-      () {
-    final a = new JsObject(context['Date'],
-                           ["December 17, 1995 03:24:00 GMT"]);
-    expect(a.callMethod('getTime'), equals(819170640000));
-  });
+    test('new Date("December 17, 1995 03:24:00 GMT")',
+        () {
+      final a = new JsObject(context['Date'],
+                             ["December 17, 1995 03:24:00 GMT"]);
+      expect(a.callMethod('getTime'), equals(819170640000));
+    });
 
-  test('js instantiation : new Date(1995,11,17)', () {
-    // Note: JS Date counts months from 0 while Dart counts from 1.
-    final a = new JsObject(context['Date'], [1995, 11, 17]);
-    final b = new DateTime(1995, 12, 17);
-    expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
-  });
+    test('new Date(1995,11,17)', () {
+      // Note: JS Date counts months from 0 while Dart counts from 1.
+      final a = new JsObject(context['Date'], [1995, 11, 17]);
+      final b = new DateTime(1995, 12, 17);
+      expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
+    });
 
-  test('js instantiation : 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]);
-    final b = new DateTime(1995, 12, 17, 3, 24, 0);
-    expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
-  });
+    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]);
+      final b = new DateTime(1995, 12, 17, 3, 24, 0);
+      expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
+    });
 
-  test('js instantiation : new Object()', () {
-    final a = new JsObject(context['Object']);
-    expect(a, isNotNull);
+    test('new Object()', () {
+      final a = new JsObject(context['Object']);
+      expect(a, isNotNull);
 
-    a['attr'] = "value";
-    expect(a['attr'], equals("value"));
-  });
+      a['attr'] = "value";
+      expect(a['attr'], equals("value"));
+    });
 
-  test(r'js instantiation : new RegExp("^\w+$")', () {
-    final a = new JsObject(context['RegExp'], [r'^\w+$']);
-    expect(a, isNotNull);
-    expect(a.callMethod('test', ['true']), isTrue);
-    expect(a.callMethod('test', [' false']), isFalse);
-  });
+    test(r'new RegExp("^\w+$")', () {
+      final a = new JsObject(context['RegExp'], [r'^\w+$']);
+      expect(a, isNotNull);
+      expect(a.callMethod('test', ['true']), isTrue);
+      expect(a.callMethod('test', [' false']), isFalse);
+    });
 
-  test('js instantiation via map notation : new Array()', () {
-    final a = new JsObject(context['Array']);
-    expect(a, isNotNull);
-    expect(a['length'], equals(0));
+    test('js instantiation via map notation : new Array()', () {
+      final a = new JsObject(context['Array']);
+      expect(a, isNotNull);
+      expect(a['length'], equals(0));
 
-    a['push'].apply(a, ["value 1"]);
-    expect(a['length'], equals(1));
-    expect(a[0], equals("value 1"));
+      a.callMethod('push', ["value 1"]);
+      expect(a['length'], equals(1));
+      expect(a[0], equals("value 1"));
 
-    a['pop'].apply(a);
-    expect(a['length'], equals(0));
-  });
+      a.callMethod('pop');
+      expect(a['length'], equals(0));
+    });
 
-  test('js instantiation via map notation : new Date()', () {
-    final a = new JsObject(context['Date']);
-    expect(a['getTime'].apply(a), isNotNull);
-  });
+    test('js instantiation via map notation : new Date()', () {
+      final a = new JsObject(context['Date']);
+      expect(a.callMethod('getTime'), isNotNull);
+    });
 
-  test('js instantiation : typed array', () {
-    if (Platform.supportsTypedData) {
-      final codeUnits = "test".codeUnits;
-      final buf = new JsObject(context['ArrayBuffer'], [codeUnits.length]);
-      final bufView = new JsObject(context['Uint8Array'], [buf]);
-      for (var i = 0; i < codeUnits.length; i++) {
-        bufView[i] = codeUnits[i];
+    test('typed array', () {
+      if (Platform.supportsTypedData) {
+        // Safari's ArrayBuffer is not a Function and so doesn't support bind
+        // which JsObject's constructor relies on.
+        // bug: https://bugs.webkit.org/show_bug.cgi?id=122976
+        if (context['ArrayBuffer']['bind'] != null) {
+          final codeUnits = "test".codeUnits;
+          final buf = new JsObject(context['ArrayBuffer'], [codeUnits.length]);
+          final bufView = new JsObject(context['Uint8Array'], [buf]);
+          for (var i = 0; i < codeUnits.length; i++) {
+            bufView[i] = codeUnits[i];
+          }
+        }
       }
-    }
+    });
+
+    test('>10 parameters', () {
+      final o = new JsObject(context['Baz'], [1,2,3,4,5,6,7,8,9,10,11]);
+      for (var i = 1; i <= 11; i++) {
+        expect(o["f$i"], i);
+      }
+      expect(o['constructor'], equals(context['Baz']));
+    });
   });
 
-  test('js instantiation : >10 parameters', () {
-    final o = new JsObject(context['Baz'], [1,2,3,4,5,6,7,8,9,10,11]);
-    for (var i = 1; i <= 11; i++) {
-      o["f$i"] = i;
-    }
+  group('JsFunction and callMethod', () {
+
+    test('JsFunction.apply on a function defined in JS', () {
+      expect(context['razzle'].apply([]), equals(42));
+    });
+
+    test('JsFunction.apply on a function that uses "this"', () {
+      var object = new Object();
+      expect(context['returnThis'].apply([], thisArg: object), same(object));
+    });
+
+    test('JsObject.callMethod on a function defined in JS', () {
+      expect(context.callMethod('razzle'), equals(42));
+      expect(() => context.callMethod('dazzle'), throwsA(isNoSuchMethodError));
+    });
+
+    test('callMethod with many arguments', () {
+      expect(context.callMethod('varArgs', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
+        equals(55));
+    });
+
+    test('access a property of a function', () {
+      expect(context.callMethod('Bar'), "ret_value");
+      expect(context['Bar']['foo'], "property_value");
+    });
+/*
+ TODO(jacobr): evaluate whether we should be in the business of throwing
+ ArgumentError outside of checked mode. In unchecked mode this should just
+ return a NoSuchMethodError as the class lacks a method "true".
+
+    test('callMethod throws if name is not a String or num', () {
+      expect(() => context.callMethod(true),
+          throwsA(new isInstanceOf<ArgumentError>()));
+    });
+*/
   });
 
-  test('write global field', () {
-    context['y'] = 42;
-    expect(context['y'], equals(42));
+  group('JsObject.fromBrowserObject()', () {
+
+    test('Nodes are proxied', () {
+      var node = new JsObject.fromBrowserObject(new DivElement());
+      context['addTestProperty'].apply([node]);
+      expect(node is JsObject, isTrue);
+      expect(node.instanceof(context['HTMLDivElement']), isTrue);
+      expect(node['testProperty'], 'test');
+    });
+
+    test('primitives and null throw ArgumentError', () {
+      for (var v in ['a', 1, 2.0, true, null]) {
+        expect(() => new JsObject.fromBrowserObject(v),
+            throwsA(new isInstanceOf<ArgumentError>()));
+      }
+    });
+
   });
 
-  test('get JS JsFunction', () {
-    var razzle = context['razzle'];
-    expect(razzle.apply(context), equals(42));
+  group('Dart callback', () {
+    test('invoke Dart callback from JS', () {
+      expect(() => context.callMethod('invokeCallback'), throws);
+
+      context['callback'] = () => 42;
+      expect(context.callMethod('invokeCallback'), equals(42));
+
+      context.deleteProperty('callback');
+    });
+
+    test('callback as parameter', () {
+      expect(context.callMethod('getTypeOf', [context['razzle']]),
+          equals("function"));
+    });
+
+    test('invoke Dart callback from JS with this', () {
+      // A JavaScript constructor function implemented in Dart which
+      // uses 'this'
+      final constructor = new JsFunction.withThis(($this, arg1) {
+        var t = $this;
+        $this['a'] = 42;
+      });
+      var o = new JsObject(constructor, ["b"]);
+      expect(o['a'], equals(42));
+    });
+
+    test('invoke Dart callback from JS with 11 parameters', () {
+      context['callbackWith11params'] = (p1, p2, p3, p4, p5, p6, p7,
+          p8, p9, p10, p11) => '$p1$p2$p3$p4$p5$p6$p7$p8$p9$p10$p11';
+      expect(context.callMethod('invokeCallbackWith11params'),
+          equals('1234567891011'));
+    });
+
+    test('return a JS proxy to JavaScript', () {
+      var result = context.callMethod('testJsMap', [() => new JsObject.jsify({'value': 42})]);
+      expect(result, 42);
+    });
+
   });
 
-  test('call JS function', () {
-    expect(context.callMethod('razzle'), equals(42));
-    expect(() => context.callMethod('dazzle'), throwsA(isNoSuchMethodError));
-  });
+  group('JsObject.jsify()', () {
 
-  test('call JS function via map notation', () {
-    expect(context['razzle'].apply(context), equals(42));
-    expect(() => context['dazzle'].apply(context),
-        throwsA(isNoSuchMethodError));
-  });
+    test('convert a List', () {
+      final list = [1, 2, 3, 4, 5, 6, 7, 8];
+      var array = new JsObject.jsify(list);
+      expect(context.callMethod('isArray', [array]), isTrue);
+      expect(array['length'], equals(list.length));
+      for (var i = 0; i < list.length ; i++) {
+        expect(array[i], equals(list[i]));
+      }
+    });
 
-  test('call JS function with varargs', () {
-    expect(context.callMethod('varArgs', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
-      equals(55));
-  });
+    test('convert an Iterable', () {
+      final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]);
+      var array = new JsObject.jsify(set);
+      expect(context.callMethod('isArray', [array]), isTrue);
+      expect(array['length'], equals(set.length));
+      for (var i = 0; i < array['length'] ; i++) {
+        expect(set.contains(array[i]), isTrue);
+      }
+    });
 
-  test('allocate JS object', () {
-    var foo = new JsObject(context['Foo'], [42]);
-    expect(foo['a'], equals(42));
-    expect(foo.callMethod('bar'), equals(42));
-    expect(() => foo.callMethod('baz'), throwsA(isNoSuchMethodError));
-  });
+    test('convert a Map', () {
+      var map = {'a': 1, 'b': 2, 'c': 3};
+      var jsMap = new JsObject.jsify(map);
+      expect(!context.callMethod('isArray', [jsMap]), isTrue);
+      for (final key in map.keys) {
+        expect(context.callMethod('checkMap', [jsMap, key, map[key]]), isTrue);
+      }
+    });
 
-  test('call toString()', () {
-    var foo = new JsObject(context['Foo'], [42]);
-    expect(foo.toString(), equals("I'm a Foo a=42"));
-    var container = context['container'];
-    expect(container.toString(), equals("[object Object]"));
-  });
-
-  test('allocate simple JS array', () {
-    final list = [1, 2, 3, 4, 5, 6, 7, 8];
-    var array = jsify(list);
-    expect(context.callMethod('isArray', [array]), isTrue);
-    expect(array['length'], equals(list.length));
-    for (var i = 0; i < list.length ; i++) {
-      expect(array[i], equals(list[i]));
-    }
-  });
-
-  test('allocate JS array with iterable', () {
-    final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]);
-    var array = jsify(set);
-    expect(context.callMethod('isArray', [array]), isTrue);
-    expect(array['length'], equals(set.length));
-    for (var i = 0; i < array['length'] ; i++) {
-      expect(set.contains(array[i]), isTrue);
-    }
-  });
-
-  test('allocate simple JS map', () {
-    var map = {'a': 1, 'b': 2, 'c': 3};
-    var jsMap = jsify(map);
-    expect(!context.callMethod('isArray', [jsMap]), isTrue);
-    for (final key in map.keys) {
-      expect(context.callMethod('checkMap', [jsMap, key, map[key]]), isTrue);
-    }
-  });
-
-  test('allocate complex JS object', () {
-    final object =
-      {
+    test('deep convert a complex object', () {
+      final object = {
         'a': [1, [2, 3]],
         'b': {
           'c': 3,
@@ -411,103 +540,231 @@
         },
         'e': null
       };
-    var jsObject = jsify(object);
-    expect(jsObject['a'][0], equals(object['a'][0]));
-    expect(jsObject['a'][1][0], equals(object['a'][1][0]));
-    expect(jsObject['a'][1][1], equals(object['a'][1][1]));
-    expect(jsObject['b']['c'], equals(object['b']['c']));
-    expect(jsObject['b']['d'], equals(object['b']['d']));
-    expect(jsObject['b']['d'].callMethod('bar'), equals(42));
-    expect(jsObject['e'], isNull);
-  });
-
-  test('invoke Dart callback from JS', () {
-    expect(() => context.callMethod('invokeCallback'), throws);
-
-    context['callback'] = new Callback(() => 42);
-    expect(context.callMethod('invokeCallback'), equals(42));
-
-    context.deleteProperty('callback');
-    expect(() => context.callMethod('invokeCallback'), throws);
-
-    context['callback'] = () => 42;
-    expect(context.callMethod('invokeCallback'), equals(42));
-
-    context.deleteProperty('callback');
-  });
-
-  test('callback as parameter', () {
-    expect(context.callMethod('getTypeOf', [context['razzle']]),
-        equals("function"));
-  });
-
-  test('invoke Dart callback from JS with this', () {
-    final constructor = new Callback.withThis(($this, arg1) {
-      $this['a'] = 42;
-      $this['b'] = jsify(["a", arg1]);
+      var jsObject = new JsObject.jsify(object);
+      expect(jsObject['a'][0], equals(object['a'][0]));
+      expect(jsObject['a'][1][0], equals(object['a'][1][0]));
+      expect(jsObject['a'][1][1], equals(object['a'][1][1]));
+      expect(jsObject['b']['c'], equals(object['b']['c']));
+      expect(jsObject['b']['d'], equals(object['b']['d']));
+      expect(jsObject['b']['d'].callMethod('bar'), equals(42));
+      expect(jsObject['e'], isNull);
     });
-    var o = new JsObject(constructor, ["b"]);
-    expect(o['a'], equals(42));
-    expect(o['b'][0], equals("a"));
-    expect(o['b'][1], equals("b"));
+
+    test('throws if object is not a Map or Iterable', () {
+      expect(() => new JsObject.jsify('a'),
+          throwsA(new isInstanceOf<ArgumentError>()));
+    });
   });
 
-  test('invoke Dart callback from JS with 11 parameters', () {
-    context['callbackWith11params'] = new Callback((p1, p2, p3, p4, p5, p6, p7,
-        p8, p9, p10, p11) => '$p1$p2$p3$p4$p5$p6$p7$p8$p9$p10$p11');
-    expect(context.callMethod('invokeCallbackWith11params'),
-        equals('1234567891011'));
+  group('JsObject methods', () {
+
+    test('hashCode and ==', () {
+      final o1 = context['Object'];
+      final o2 = context['Object'];
+      expect(o1 == o2, isTrue);
+      expect(o1.hashCode == o2.hashCode, isTrue);
+      final d = context['document'];
+      expect(o1 == d, isFalse);
+    });
+
+    test('toString', () {
+      var foo = new JsObject(context['Foo'], [42]);
+      expect(foo.toString(), equals("I'm a Foo a=42"));
+      var container = context['container'];
+      expect(container.toString(), equals("[object Object]"));
+    });
+
+    test('toString returns a String even if the JS object does not', () {
+      var foo = new JsObject(context['Liar']);
+      expect(foo.callMethod('toString'), 1);
+      expect(foo.toString(), '1');
+    });
+
+    test('instanceof', () {
+      var foo = new JsObject(context['Foo'], [1]);
+      expect(foo.instanceof(context['Foo']), isTrue);
+      expect(foo.instanceof(context['Object']), isTrue);
+      expect(foo.instanceof(context['String']), isFalse);
+    });
+
+    test('deleteProperty', () {
+      var object = new JsObject.jsify({});
+      object['a'] = 1;
+      expect(context['Object'].callMethod('keys', [object])['length'], 1);
+      expect(context['Object'].callMethod('keys', [object])[0], "a");
+      object.deleteProperty("a");
+      expect(context['Object'].callMethod('keys', [object])['length'], 0);
+    });
+
+/* TODO(jacobr): this is another test that is inconsistent with JS semantics.
+    test('deleteProperty throws if name is not a String or num', () {
+      var object = new JsObject.jsify({});
+      expect(() => object.deleteProperty(true),
+          throwsA(new isInstanceOf<ArgumentError>()));
+    });
+  */
+
+    test('hasProperty', () {
+      var object = new JsObject.jsify({});
+      object['a'] = 1;
+      expect(object.hasProperty('a'), isTrue);
+      expect(object.hasProperty('b'), isFalse);
+    });
+
+/* TODO(jacobr): is this really the correct unchecked mode behavior?
+    test('hasProperty throws if name is not a String or num', () {
+      var object = new JsObject.jsify({});
+      expect(() => object.hasProperty(true),
+          throwsA(new isInstanceOf<ArgumentError>()));
+    });
+*/
+
+    test('[] and []=', () {
+      final myArray = context['myArray'];
+      expect(myArray['length'], equals(1));
+      expect(myArray[0], equals("value1"));
+      myArray[0] = "value2";
+      expect(myArray['length'], equals(1));
+      expect(myArray[0], equals("value2"));
+
+      final foo = new JsObject(context['Foo'], [1]);
+      foo["getAge"] = () => 10;
+      expect(foo.callMethod('getAge'), equals(10));
+    });
+
+/* TODO(jacobr): remove as we should only throw this in checked mode.
+    test('[] and []= throw if name is not a String or num', () {
+      var object = new JsObject.jsify({});
+      expect(() => object[true],
+          throwsA(new isInstanceOf<ArgumentError>()));
+      expect(() => object[true] = 1,
+          throwsA(new isInstanceOf<ArgumentError>()));
+    });
+*/
   });
 
-  test('return a JS proxy to JavaScript', () {
-    var result = context.callMethod('testJsMap', [() => jsify({'value': 42})]);
-    expect(result, 42);
-  });
+  group('transferrables', () {
 
-  test('test instanceof', () {
-    var foo = new JsObject(context['Foo'], [1]);
-    expect(foo.instanceof(context['Foo']), isTrue);
-    expect(foo.instanceof(context['Object']), isTrue);
-    expect(foo.instanceof(context['String']), isFalse);
-  });
+    group('JS->Dart', () {
 
-  test('test deleteProperty', () {
-    var object = jsify({});
-    object['a'] = 1;
-    expect(context['Object'].callMethod('keys', [object])['length'], 1);
-    expect(context['Object'].callMethod('keys', [object])[0], "a");
-    object.deleteProperty("a");
-    expect(context['Object'].callMethod('keys', [object])['length'], 0);
-  });
+      test('Date', () {
+        var date = context.callMethod('getNewDate');
+        expect(date is Date, isTrue);
+      });
 
-  test('test hasProperty', () {
-    var object = jsify({});
-    object['a'] = 1;
-    expect(object.hasProperty('a'), isTrue);
-    expect(object.hasProperty('b'), isFalse);
-  });
+      test('window', () {
+        expect(context['window'] is Window, isFalse);
+      });
 
-  test('test index get and set', () {
-    final myArray = context['myArray'];
-    expect(myArray['length'], equals(1));
-    expect(myArray[0], equals("value1"));
-    myArray[0] = "value2";
-    expect(myArray['length'], equals(1));
-    expect(myArray[0], equals("value2"));
+      test('document', () {
+        expect(context['document'] is Document, isTrue);
+      });
 
-    final foo = new JsObject(context['Foo'], [1]);
-    foo["getAge"] = () => 10;
-    expect(foo.callMethod('getAge'), equals(10));
-  });
+      test('Blob', () {
+        var blob = context.callMethod('getNewBlob');
+        expect(blob is Blob, isTrue);
+        expect(blob.type, equals('text/html'));
+      });
 
-  test('access a property of a function', () {
-    expect(context.callMethod('Bar'), "ret_value");
-    expect(context['Bar']['foo'], "property_value");
-  });
+      test('unattached DivElement', () {
+        var node = context.callMethod('getNewDivElement');
+        expect(node is Div, isTrue);
+      });
 
-  test('usage of Serializable', () {
-    final red = Color.RED;
-    context['color'] = red;
-    expect(context['color'], equals(red._value));
+      test('KeyRange', () {
+        if (IdbFactory.supported) {
+          var node = context.callMethod('getNewIDBKeyRange');
+          expect(node is KeyRange, isTrue);
+        }
+      });
+
+      test('ImageData', () {
+        var node = context.callMethod('getNewImageData');
+        expect(node is ImageData, isTrue);
+      });
+
+      test('typed data: Int32Array', () {
+        var list = context.callMethod('getNewInt32Array');
+        print(list);
+        expect(list is Int32List, isTrue);
+        expect(list, orderedEquals([1, 2, 3, 4, 5, 6, 7, 8]));
+      });
+
+    });
+
+    group('Dart->JS', () {
+
+      test('Date', () {
+        context['o'] = new DateTime(1995, 12, 17);
+        var dateType = context['Date'];
+        expect(context.callMethod('isPropertyInstanceOf', ['o', dateType]),
+            isTrue);
+        context.deleteProperty('o');
+      });
+
+      test('window', () {
+        context['o'] = window;
+        var windowType = context['Window'];
+        expect(context.callMethod('isPropertyInstanceOf', ['o', windowType]),
+            isFalse);
+        context.deleteProperty('o');
+      });
+
+      test('document', () {
+        context['o'] = document;
+        var documentType = context['Document'];
+        expect(context.callMethod('isPropertyInstanceOf', ['o', documentType]),
+            isTrue);
+        context.deleteProperty('o');
+      });
+
+      test('Blob', () {
+        var fileParts = ['<a id="a"><b id="b">hey!</b></a>'];
+        context['o'] = new Blob(fileParts, 'text/html');
+        var blobType = context['Blob'];
+        expect(context.callMethod('isPropertyInstanceOf', ['o', blobType]),
+            isTrue);
+        context.deleteProperty('o');
+      });
+
+      test('unattached DivElement', () {
+        context['o'] = new DivElement();
+        var divType = context['HTMLDivElement'];
+        expect(context.callMethod('isPropertyInstanceOf', ['o', divType]),
+            isTrue);
+        context.deleteProperty('o');
+      });
+
+      test('KeyRange', () {
+        if (IdbFactory.supported) {
+          context['o'] = new KeyRange.only(1);
+          var keyRangeType = context['IDBKeyRange'];
+          expect(context.callMethod('isPropertyInstanceOf', ['o', keyRangeType]),
+              isTrue);
+          context.deleteProperty('o');
+        }
+      });
+
+      test('ImageData', () {
+        var canvas = new CanvasElement();
+        var ctx = canvas.getContext('2d');
+        context['o'] = ctx.createImageData(1, 1);
+        var imageDataType = context['ImageData'];
+        expect(context.callMethod('isPropertyInstanceOf', ['o', imageDataType]),
+            isTrue);
+        context.deleteProperty('o');
+      });
+
+      test('typed data: Int32List', () {
+        context['o'] = new Int32List.fromList([1, 2, 3, 4]);
+        var listType = context['Int32Array'];
+        // TODO(jacobr): make this test pass. Currently some type information
+        // is lost when typed arrays are passed between JS and Dart.
+        // expect(context.callMethod('isPropertyInstanceOf', ['o', listType]),
+        //    isTrue);
+        context.deleteProperty('o');
+      });
+
+    });
   });
 }
diff --git a/tests/html/selectelement_test.dart b/tests/html/selectelement_test.dart
index f88c4af..81eb13d 100644
--- a/tests/html/selectelement_test.dart
+++ b/tests/html/selectelement_test.dart
@@ -16,11 +16,9 @@
     var options = [
       new OptionElement(),
       new DivElement(),
-      new OptionElement(data: 'data', value: 'two', defaultSelected: false,
-          selected: true),
+      new OptionElement(data: 'data', value: 'two', selected: true),
       new DivElement(),
-      new OptionElement(data: 'data', value: 'two', defaultSelected: false,
-          selected: true),
+      new OptionElement(data: 'data', value: 'two', selected: true),
       new OptionElement(),
     ];
     element.children.addAll(options);
@@ -34,12 +32,11 @@
     var options = [
       new OptionElement(),
       new DivElement(),
-      new OptionElement(data: 'data', value: 'two', defaultSelected: false,
-          selected: true),
+      new OptionElement(data: 'data', value: 'two', selected: true),
       new DivElement(),
-      new OptionElement(data: 'data', value: 'two', defaultSelected: false,
-          selected: true),
+      new OptionElement(data: 'data', value: 'two', selected: true),
       new OptionElement(),
+      new OptionElement(data: 'data', value: 'two', selected: false),
     ];
     element.children.addAll(options);
     expect(element.selectedOptions.length, 2);
@@ -51,10 +48,8 @@
     var element = new SelectElement();
     var options = [
       new OptionElement(),
-      new OptionElement(data: 'data', value: 'two', defaultSelected: false,
-          selected: true),
-      new OptionElement(data: 'data', value: 'two', defaultSelected: false,
-          selected: true),
+      new OptionElement(data: 'data', value: 'two', selected: true),
+      new OptionElement(data: 'data', value: 'two', selected: true),
       new OptionElement(),
     ];
     element.children.addAll(options);
diff --git a/tests/html/xhr_test.dart b/tests/html/xhr_test.dart
index b39ab1c..78b8c5a 100644
--- a/tests/html/xhr_test.dart
+++ b/tests/html/xhr_test.dart
@@ -246,4 +246,16 @@
           }));
     });
   });
+
+  group('headers', () {
+    test('xhr responseHeaders', () {
+      return HttpRequest.request(url).then(
+        (xhr) {
+          var serverHeader = xhr.responseHeaders['server'];
+          expect(serverHeader, isNotNull);
+          // Should be like: 'Dart/0.1 (dart:io)'
+          expect(serverHeader.startsWith('Dart/'), isTrue);
+        });
+    });
+  });
 }
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 6db194c..70a991d 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -18,10 +18,6 @@
 spawn_uri_vm_negative_test: Fail
 unresolved_ports_negative_test: Fail
 
-[ $compiler == dartanalyzer ]
-# pkg issue 13945; Missing inherited member 'Trace.frames'
-spawn_uri_multi_test/none: fail
-
 [ $compiler == dart2js && $jscl ]
 browser/*: SkipByDesign  # Browser specific tests
 illegal_msg_stream_test: RuntimeError # Issue 6750
diff --git a/tests/language/constant_type_literal_test.dart b/tests/language/constant_type_literal_test.dart
new file mode 100644
index 0000000..a63ec1b
--- /dev/null
+++ b/tests/language/constant_type_literal_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// Test for type literals as compile-time constants.
+
+class C<T> {
+  void m() {
+    const List lst = const [
+                            T /// 01: compile-time error
+                             ];
+  }
+}
+
+main() {
+  new C().m();
+}
diff --git a/tests/language/cyclic_typedef_test.dart b/tests/language/cyclic_typedef_test.dart
index 61d8d0b..c660527 100644
--- a/tests/language/cyclic_typedef_test.dart
+++ b/tests/language/cyclic_typedef_test.dart
@@ -13,6 +13,12 @@
 
 A // The name of the typedef
 
+// Cyclic through type variable bound.
+<T extends A> /// 10: compile-time error
+
+// Cyclic through generic type variable bound.
+<T extends List<A>> /// 11: compile-time error
+
 ( // The left parenthesis of the typedef arguments.
 
 // Cyclic through parameter type.
@@ -39,11 +45,23 @@
 // Cyclic through another more typedefs.
 C c /// 09: compile-time error
 
+// Reference through a class is not a cyclic self-reference.
+Class c /// 12: ok
+
+// Reference through a class type bound is not a cyclic self-reference.
+Class c /// 13: ok
+
 ); // The right parenthesis of the typedef arguments.
 
 typedef B(A a);
 typedef C(B b);
 
+class Class
+<T extends A> /// 13: continued
+{
+  A a; /// 12: continued
+}
+
 void testA(A a) {}
 
 void main() {
diff --git a/tests/language/language.status b/tests/language/language.status
index 9149d19..e720d3e 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -14,12 +14,6 @@
 built_in_identifier_prefix_test: Fail # Issue 6970
 library_juxtaposition_test: Fail # Issue 6877
 throwing_lazy_variable_test: Fail # Issue 5802
-type_variable_conflict_test/01: Fail # Issue 13701
-type_variable_conflict_test/02: Fail # Issue 13701
-type_variable_conflict_test/03: Fail # Issue 13701
-type_variable_conflict_test/04: Fail # Issue 13701
-type_variable_conflict_test/05: Fail # Issue 13701
-type_variable_conflict_test/06: Fail # Issue 13701
 f_bounded_equality_test: RuntimeError # Issue 14000
 
 # These bugs refer currently ongoing language discussions.
@@ -36,10 +30,12 @@
 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
 
-
 [ $compiler == none && $runtime == vm && $checked ]
 compile_time_constant_checked3_test/01: MissingCompileTimeError # Issue 13685
 compile_time_constant_checked3_test/02: MissingCompileTimeError # Issue 13685
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 459bd74..f26cea0 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -29,6 +29,18 @@
 
 built_in_identifier_test/none: Fail # Issue 13023
 
+# test issue 13807, missing support for type promotion
+type_promotion_closure_test/none: Fail # Issue 13807
+type_promotion_functions_test/none: Fail # Issue 13807
+type_promotion_local_test/none: Fail # Issue 13807
+type_promotion_logical_and_test/none: Fail # Issue 13807
+type_promotion_multiple_test/none: Fail # Issue 13807
+type_promotion_parameter_test/none: Fail # Issue 13807
+
+# Missing checks for cyclic typedefs (through bounds)
+cyclic_typedef_test/10: Fail # Issue 13906
+cyclic_typedef_test/11: Fail # Issue 13906
+
 
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
@@ -176,18 +188,14 @@
 malformed_test/05: fail # test issue 14079, it is not error, but warning to instantiate malformed type
 malformed_test/06: fail # test issue 14079, it is not error, but warning to use malformed type in "try-on" clause
 
+# test issue 14228
+black_listed_test/none: fail # test issue 14228, warnings are required but not expected
+
 #
 # Please don't add new items here.
 # This is section for invalid tests.
 #
 
-type_promotion_closure_test/none: Fail # Issue 13807
-type_promotion_functions_test/none: Fail # Issue 13807
-type_promotion_local_test/none: Fail # Issue 13807
-type_promotion_logical_and_test/none: Fail # Issue 13807
-type_promotion_multiple_test/none: Fail # Issue 13807
-type_promotion_parameter_test/none: Fail # Issue 13807
-
 [ $compiler == dartanalyzer && $checked ]
 factory1_test/00: fail
 factory1_test/01: fail
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index a757e63..1076d46 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -3,8 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2analyzer ]
-switch_bad_case_test/02: Fail # missing error in double in switch case expr
-
 # Runtime negative test. No static errors or warnings.
 closure_call_wrong_argument_count_negative_test: skip
 
@@ -15,29 +13,11 @@
 class_literal_test: fail
 constructor_call_as_function_test/01: fail
 
-# TBF: It is a static type warning if a type parameter is a supertype of its upper bound.
-cyclic_type_variable_test/01: fail
-cyclic_type_variable_test/02: fail
-cyclic_type_variable_test/03: fail
-cyclic_type_variable_test/04: fail
-
-# TBF: 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/01: fail # Issue 12701
-
 # 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
 
-# TBD: F-bounded quantification
-f_bounded_quantification_test/01: fail # Issue 12704
-f_bounded_quantification_test/02: fail # Issue 12704
-
 function_type_alias9_test/00: crash # Issue 11987
 
-list_literal_syntax_test/01: fail # Issue 12103
-list_literal_syntax_test/02: fail # Issue 12103
-list_literal_syntax_test/03: fail # Issue 12103
-malformed_test/none: fail # Issue 12696
-
 # TBF: we should check conflicts not only for methods, but for accessors too
 override_field_test/02: fail
 override_field_test/03: fail
@@ -47,17 +27,34 @@
 # TBF: prefix T hidden by type variable T in 'new T.Class()'
 prefix10_negative_test: fail
 
-# TBF: no error if A in our library, B extends A in other library, reference B._private from Test extends B in our library.
-private_member1_negative_test: fail
-private_member2_negative_test: fail
-private_member3_negative_test: fail
-
 built_in_identifier_test/none: Fail # Issue 13023
 
+# test issue 13807, missing support for type promotion
+type_promotion_closure_test/none: Fail # Issue 13807
+type_promotion_functions_test/none: Fail # Issue 13807
+type_promotion_local_test/none: Fail # Issue 13807
+type_promotion_logical_and_test/none: Fail # Issue 13807
+type_promotion_multiple_test/none: Fail # Issue 13807
+type_promotion_parameter_test/none: Fail # Issue 13807
+
+# Missing checks for cyclic typedefs (through bounds)
+cyclic_typedef_test/10: Fail # Issue 13906
+cyclic_typedef_test/11: Fail # Issue 13906
+
+
+# Please add new failing tests before this line.
+# Section below is for invalid tests.
+#
+#
+
+
+
+
 # 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
 final_syntax_test/04: Fail # Issue 11124
@@ -82,13 +79,10 @@
 
 # test issue 11578, redirecting factory with not subtype
 factory5_test/none: fail # Issue 11578
-factory_redirection_test/none: fail # Issue 11578
 type_variable_bounds_test/none: fail # Issue 11578
 type_variable_scope_test/none: fail # Issue 11578
 factory_implementation_test/none: fail # Issue 11578
 
-redirecting_factory_malbounded_test/none: Fail # Issue 12827
-
 # test issue 11579, assignment, no setter
 getter_no_setter_test/none: fail
 
@@ -150,14 +144,6 @@
 # test issue 12161, type variable in static, malformed type, static warning
 type_variable_static_context_negative_test: fail
 
-# test issue 12162, 'a' has dynamic type, so it statically it is assignable to anything
-type_variable_bounds2_test/00: fail # Issue 12162
-type_variable_bounds2_test/01: fail # Issue 12162
-type_variable_bounds2_test/02: fail # Issue 12162
-type_variable_bounds2_test/03: fail # Issue 12162
-type_variable_bounds2_test/04: fail # Issue 12162
-type_variable_bounds2_test/06: fail # Issue 12162
-
 # test issue 12163, unresolved identifier is static warning in static context
 unresolved_in_factory_negative_test: fail # Issue 12163
 unresolved_top_level_var_negative_test: fail # Issue 12163
@@ -186,12 +172,29 @@
 # test issue 13787; duplicate exports of the same declaration is not handled
 duplicate_export_test: fail # Issue 13787
 
-type_variable_conflict_test/01: Fail # Issue 13703
-type_variable_conflict_test/02: Fail # Issue 13703
-type_variable_conflict_test/03: Fail # Issue 13703
-type_variable_conflict_test/04: Fail # Issue 13703
-type_variable_conflict_test/05: Fail # Issue 13703
-type_variable_conflict_test/06: Fail # Issue 13703
+# test issue 13916, Looks as no warning should be in this redirecting factory
+redirecting_factory_infinite_steps_test/01: fail
+
+# 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
+
+# test issue 14021, it is warning, not an error to reference private (undefined) identifier
+private_member1_negative_test: fail
+private_member2_negative_test: fail
+private_member3_negative_test: fail
+
+# test issue 14079
+malformed_test/none: fail # test issue 14079, legit warnings for malformed type
+malformed_test/05: fail # test issue 14079, it is not error, but warning to instantiate malformed type
+malformed_test/06: fail # test issue 14079, it is not error, but warning to use malformed type in "try-on" clause
+
+# test issue 14228
+black_listed_test/none: fail # test issue 14228, warnings are required but not expected
+
+#
+# Please don't add new items here.
+# This is section for invalid tests.
+#
 
 [ $compiler == dart2analyzer && $checked ]
 factory1_test/00: fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 8c5fd50..8e5d476 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -93,7 +93,6 @@
 
 [ $compiler == dart2js ]
 malformed_test/none: RuntimeError # Issue 12695
-function_type_alias9_test/00: Crash # Issue 9792
 branch_canonicalization_test: RuntimeError # Issue 638.
 identical_closure2_test: RuntimeError # Issue 1533, Issue 12596
 integer_division_by_zero_test: RuntimeError # Issue 8301
@@ -194,7 +193,6 @@
 
 [ $compiler == dart2dart ]
 regress_13494_test: Fail # Issue 13494
-function_type_alias9_test/00: Crash # Issue 11986
 malformed_test/none: CompileTimeError # Issue 12695
 mixin_super_constructor_named_test: Fail # Issue 12631
 mixin_super_constructor_positionals_test: Fail # Issue 12631
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index b8a685b..bfa469b 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -1,11 +1,3 @@
 # 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 == dart2analyzer ]
-lib/async/async: fail
-lib/core/core: fail
-lib/typed_data/typed_data: fail
-lib/io/io: fail
-lib/json/json: fail
-lib/utf/utf: fail
diff --git a/tests/lib/async/zone_run_test.dart b/tests/lib/async/zone_run_test.dart
index 8cb62f3..2af32df 100644
--- a/tests/lib/async/zone_run_test.dart
+++ b/tests/lib/async/zone_run_test.dart
@@ -16,7 +16,7 @@
       run: (Zone self, ZoneDelegate parent, Zone origin, f()) {
         // The zone is still the same as when origin.run was invoked, which
         // is the root zone. (The origin zone hasn't been set yet).
-        Expect.identical(Zone.current, Zone.ROOT);
+        Expect.identical(Zone.ROOT, Zone.current);
         events.add("forked.run");
         if (shouldForward) return parent.run(origin, f);
         return 42;
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 7b0bbd1..6b801d3 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -2,11 +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.
 
-[ $runtime == dartium || $runtime == drt ]
-async/zone_run_guarded_test: Skip # Issue 14146
-async/zone_run_test: Skip # Issue 14146
-async/run_zoned9_test: Skip # Issue 14146
-
 [ $csp ]
 mirrors/delegate_test: RuntimeError # Issue 13864
 
@@ -179,15 +174,12 @@
 mirrors/mixin_application_test/01: Fail, OK # TODO(ahe): Slight broken test to ensure test coverage on dart2js.
 mirrors/intercepted_object_test: Fail, OK # TODO(ahe): Slight broken test to ensure test coverage on dart2js.
 mirrors/typedef_test/01: Fail, OK # Incorrect dart2js behavior.
-mirrors/closures_test/01: Fail, OK # Incorrect dart2js behavior.
 
 mirrors/generic_function_typedef_test: RuntimeError # Issue 12282
 mirrors/generic_f_bounded_test: RuntimeError # Issue 14000
-mirrors/generic_interface_test/01: RuntimeError # Issue 14113
 mirrors/immutable_collections_test: RuntimeError # Issue 14027
 mirrors/symbol_validation_test: RuntimeError # Issue 13596
-mirrors/generic_mixin_test/01: RuntimeError # Issue 14114
-mirrors/generic_mixin_test/02: RuntimeError # Issue 14113
+mirrors/typevariable_mirror_metadata_test/none: RuntimeError # Issue 12282
 
 async/timer_isolate_test: Skip # See Issue 4997
 async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
@@ -219,9 +211,7 @@
 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
-
-# test issue 14016
-mirrors/typevariable_mirror_metadata_test: fail
+mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
 
 [ $compiler == dart2analyzer ]
 mirrors/typedef_test/none: Fail # Issue 13093
@@ -232,12 +222,7 @@
 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
-
-# Will be fixed by next roll?
-mirrors/typedef_metadata_test: Fail
-mirrors/mixin_test: Fail
-mirrors/mixin_application_test/none: Fail
-mirrors/generic_mixin_applications_test: Fail
+mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
 
 [ $compiler == none && $runtime == dartium ]
 async/schedule_microtask5_test: Pass, Timeout # Issue 13719: Please triage this failure.
diff --git a/tests/lib/mirrors/class_mirror_type_variables_test.dart b/tests/lib/mirrors/class_mirror_type_variables_test.dart
index ee7baf9..2a3ea7e 100644
--- a/tests/lib/mirrors/class_mirror_type_variables_test.dart
+++ b/tests/lib/mirrors/class_mirror_type_variables_test.dart
@@ -6,15 +6,44 @@
 
 import "package:expect/expect.dart";
 
+class NoTypeParams {}
+class A<T, S extends String> {}
+class B<Z extends B<Z>> {}
 class C<R,S,T> {
   R foo(R r) => r;
   S bar(S s) => s;
   T baz(T t) => t;
 }
 
-class NoTypeParams {}
+testNoTypeParams() {
+  ClassMirror cm = reflectClass(NoTypeParams);
+  Expect.equals(cm.typeVariables.length, 0);
+}
 
-main() {
+void testA() {
+  ClassMirror a = reflectClass(A);
+  Expect.equals(2, a.typeVariables.length);
+
+  TypeVariableMirror aT = a.typeVariables[0];
+  TypeVariableMirror aS = a.typeVariables[1];
+  TypeMirror aTBound = aT.upperBound.originalDeclaration;
+  TypeMirror aSBound = aS.upperBound.originalDeclaration;
+
+  Expect.equals(reflectClass(Object), aTBound);
+  Expect.equals(reflectClass(String), aSBound);
+}
+
+void testB() {
+  ClassMirror b = reflectClass(B);
+  Expect.equals(1, b.typeVariables.length);
+
+  TypeVariableMirror bZ = b.typeVariables[0];
+  ClassMirror bZBound = bZ.upperBound.originalDeclaration;
+  Expect.equals(b, bZBound);
+  Expect.equals(bZ, bZBound.typeVariables[0]);
+}
+
+testC() {
   ClassMirror cm;
   cm = reflectClass(C);
   Expect.equals(3, cm.typeVariables.length);
@@ -25,6 +54,11 @@
   Expect.equals(#R, values.elementAt(0).simpleName);
   Expect.equals(#S, values.elementAt(1).simpleName);
   Expect.equals(#T, values.elementAt(2).simpleName);
-  cm = reflectClass(NoTypeParams);
-  Expect.equals(cm.typeVariables.length, 0);
 }
+
+main() {
+  testNoTypeParams();
+  testA();
+  testB();
+  testC();
+}
\ No newline at end of file
diff --git a/tests/lib/mirrors/function_type_mirror_test.dart b/tests/lib/mirrors/function_type_mirror_test.dart
index f712d73..3b547e3 100644
--- a/tests/lib/mirrors/function_type_mirror_test.dart
+++ b/tests/lib/mirrors/function_type_mirror_test.dart
@@ -11,7 +11,7 @@
 bar(int a) {}
 
 main() {
-  TypedefMirror tm = reflectClass(FooFunction);
+  TypedefMirror tm = reflectType(FooFunction);
   FunctionTypeMirror ftm = tm.referent;
   Expect.equals(const Symbol('void'), ftm.returnType.simpleName);
   Expect.equals(#int, ftm.parameters[0].type.simpleName);
diff --git a/tests/lib/mirrors/generic_function_typedef_test.dart b/tests/lib/mirrors/generic_function_typedef_test.dart
index 051f25d..a2ce1f6 100644
--- a/tests/lib/mirrors/generic_function_typedef_test.dart
+++ b/tests/lib/mirrors/generic_function_typedef_test.dart
@@ -20,6 +20,8 @@
   GenericTransform<R> transformOfR;
 }
 
+reflectClass(t) => reflectType(t).originalDeclaration;
+
 main() {
   TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
 
diff --git a/tests/lib/mirrors/generic_mixin_test.dart b/tests/lib/mirrors/generic_mixin_test.dart
index ac9fbd3..c359d78 100644
--- a/tests/lib/mirrors/generic_mixin_test.dart
+++ b/tests/lib/mirrors/generic_mixin_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 test.generic_mixin_applications;
+library test.generic_mixin;
 
 import 'dart:mirrors';
 
@@ -63,8 +63,7 @@
   typeArguments(reflectClass(GenericMultipleMixins).mixin, []);
   typeArguments(reflectClass(GenericMultipleMixins).superclass.mixin, [reflectClass(GenericMultipleMixins).typeVariables[2]]);
   typeArguments(reflectClass(GenericMultipleMixins).superclass.superclass.mixin, [reflectClass(GenericMultipleMixins).typeVariables[1]]);
-  // 1 - VM fails here because of equality between type parameters
-  typeArguments(reflectClass(GenericMultipleMixins).superclass.superclass.superclass.mixin, [reflectClass(GenericMultipleMixins).typeVariables[0]]);  /// 01: ok
+  typeArguments(reflectClass(GenericMultipleMixins).superclass.superclass.superclass.mixin, [reflectClass(GenericMultipleMixins).typeVariables[0]]);
 
 
   typeParameters(reflect(new NonGenericMixinApplication1()).type.mixin, [#M]);
@@ -84,10 +83,9 @@
   typeParameters(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.superclass.mixin, [#M]);
   typeParameters(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.superclass.superclass.mixin, [#S]);
 
-  // 2 - VM fails here because of failure to substitute
   typeArguments(reflect(new NonGenericMixinApplication1()).type.mixin, [dynamicMirror]);
   typeArguments(reflect(new NonGenericMixinApplication2()).type.mixin, [reflectClass(String)]);
-  typeArguments(reflect(new GenericMixinApplication1<bool>()).type.mixin, [reflectClass(bool)]);  /// 02: ok
+  typeArguments(reflect(new GenericMixinApplication1<bool>()).type.mixin, [reflectClass(bool)]);
   typeArguments(reflect(new GenericMixinApplication2<bool>()).type.mixin, [reflectClass(String)]);
   typeArguments(reflect(new NonGenericClass1()).type.mixin, []);
   typeArguments(reflect(new NonGenericClass2()).type.mixin, []);
@@ -95,10 +93,10 @@
   typeArguments(reflect(new GenericClass2<bool>()).type.mixin, [reflectClass(bool)]);
   typeArguments(reflect(new NonGenericClass1()).type.superclass.mixin, [dynamicMirror]);
   typeArguments(reflect(new NonGenericClass2()).type.superclass.mixin, [reflectClass(String)]);
-  typeArguments(reflect(new GenericClass1<bool>()).type.superclass.mixin, [reflectClass(bool)]);  /// 02: ok
+  typeArguments(reflect(new GenericClass1<bool>()).type.superclass.mixin, [reflectClass(bool)]);
   typeArguments(reflect(new GenericClass2<bool>()).type.superclass.mixin, [reflectClass(String)]);
   typeArguments(reflect(new GenericMultipleMixins<bool, String, int>()).type.mixin, [reflectClass(bool), reflectClass(String), reflectClass(int)]);
-  typeArguments(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.mixin, [reflectClass(int)]);  /// 02: ok
-  typeArguments(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.superclass.mixin, [reflectClass(String)]);  /// 02: ok
-  typeArguments(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.superclass.superclass.mixin, [reflectClass(bool)]);  /// 02: ok
+  typeArguments(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.mixin, [reflectClass(int)]);
+  typeArguments(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.superclass.mixin, [reflectClass(String)]);
+  typeArguments(reflect(new GenericMultipleMixins<bool, String, int>()).type.superclass.superclass.superclass.mixin, [reflectClass(bool)]);
 }
diff --git a/tests/lib/mirrors/mirrors_test.dart b/tests/lib/mirrors/mirrors_test.dart
index b0d1b84..ba11c72 100644
--- a/tests/lib/mirrors/mirrors_test.dart
+++ b/tests/lib/mirrors/mirrors_test.dart
@@ -39,45 +39,36 @@
   var instance = new Class();
   var instMirror = reflect(instance);
 
-  expect(instMirror.invoke(const Symbol("m"),['A', 'B', instance]).reflectee,
+  expect(instMirror.invoke(#m, ['A', 'B', instance]).reflectee,
          equals({"a": 'A', "b":'B', "c": instance}));
-  expect(instMirror.invoke(const Symbol("notDefined"), []).reflectee,
+  expect(instMirror.invoke(#notDefined, []).reflectee,
          equals("DNU"));
-  expect(instMirror.invoke(const Symbol("m"), []).reflectee,
+  expect(instMirror.invoke(#m, []).reflectee,
          equals("DNU"));  // Wrong arity.
-  // TODO(rmacnak): Implement access to private members.
-  // expect(instMirror.invoke(const Symbol("_n"), [3, 4]).reflectee,
-  //        equals(7));
 
   var classMirror = instMirror.type;
-  expect(classMirror.invoke(const Symbol("s"),['A', 'B', instance]).reflectee,
+  expect(classMirror.invoke(#s, ['A', 'B', instance]).reflectee,
          equals({"a": 'A', "b":'B', "c": instance}));
-  expect(() => classMirror.invoke(const Symbol("notDefined"), []).reflectee,
+  expect(() => classMirror.invoke(#notDefined, []).reflectee,
          throws);
-  expect(() => classMirror.invoke(const Symbol("s"), []).reflectee,
+  expect(() => classMirror.invoke(#s, []).reflectee,
          throws);  // Wrong arity.
-  // TODO(rmacnak): Implement access to private members.
-  // expect(classMirror.invoke(const Symbol("_t"), [3, 4]).reflectee,
-  //        equals(7));
 
   var libMirror = classMirror.owner;
-  expect(libMirror.invoke(const Symbol("u"),['A', 'B', instance]).reflectee,
+  expect(libMirror.invoke(#u, ['A', 'B', instance]).reflectee,
          equals({"a": 'A', "b":'B', "c": instance}));
-  expect(() => libMirror.invoke(const Symbol("notDefined"), []).reflectee,
+  expect(() => libMirror.invoke(#notDefined, []).reflectee,
          throws);
-  expect(() => libMirror.invoke(const Symbol("u"), []).reflectee,
+  expect(() => libMirror.invoke(#u, []).reflectee,
          throws);  // Wrong arity.
-  // NB: This works on the VM but fails at compile-time on dart2js.
-  // expect(libMirror.invoke(const Symbol("_v"), [3, 4]).reflectee,
-  //        equals(7));
 }
 
 testInstanceFieldAccess(mirrors) {
   var instance = new Class();
   var instMirror = reflect(instance);
 
-  instMirror.setFieldAsync(const Symbol('field'), 44);
-  instMirror.getFieldAsync(const Symbol('field')).then(
+  instMirror.setFieldAsync(#field, 44);
+  instMirror.getFieldAsync(#field).then(
       expectAsync1((resultMirror) {
         expect(resultMirror.reflectee, equals(44));
         expect(instance.field, equals(44));
@@ -90,17 +81,17 @@
   var instance = 1;
   var instMirror = reflect(instance);
 
-  expect(instMirror.invoke(const Symbol('toString'), []).reflectee,
+  expect(instMirror.invoke(#toString, []).reflectee,
          equals('1'));
 
   instance = [];
   instMirror = reflect(instance);
-  instMirror.setField(const Symbol('length'), 44);
-  var resultMirror = instMirror.getField(const Symbol('length'));
+  instMirror.setField(#length, 44);
+  var resultMirror = instMirror.getField(#length);
   expect(resultMirror.reflectee, equals(44));
   expect(instance.length, equals(44));
 
-  expect(instMirror.invoke(const Symbol('toString'), []).reflectee,
+  expect(instMirror.invoke(#toString, []).reflectee,
          equals('[null, null, null, null, null, null, null, null, null, null,'
                 ' null, null, null, null, null, null, null, null, null, null,'
                 ' null, null, null, null, null, null, null, null, null, null,'
@@ -111,36 +102,36 @@
 testFieldAccess(mirrors) {
   var instance = new Class();
 
-  var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single;
-  var classMirror = libMirror.classes[const Symbol("Class")];
+  var libMirror = mirrors.findLibrary(#MirrorsTest).single;
+  var classMirror = libMirror.classes[#Class];
   var instMirror = reflect(instance);
-  var fieldMirror = classMirror.members[const Symbol('field')];
+  var fieldMirror = classMirror.members[#field];
   var future;
 
   expect(fieldMirror is VariableMirror, isTrue);
   expect(fieldMirror.type, equals(mirrors.dynamicType));
 
-  libMirror.setField(const Symbol('topLevelField'), [91]);
-  expect(libMirror.getField(const Symbol('topLevelField')).reflectee,
+  libMirror.setField(#topLevelField, [91]);
+  expect(libMirror.getField(#topLevelField).reflectee,
          equals([91]));
   expect(topLevelField, equals([91]));
 
-  libMirror.setFieldAsync(const Symbol('topLevelField'), 42);
-  future = libMirror.getFieldAsync(const Symbol('topLevelField'));
+  libMirror.setFieldAsync(#topLevelField, 42);
+  future = libMirror.getFieldAsync(#topLevelField);
   future.then(expectAsync1((resultMirror) {
     expect(resultMirror.reflectee, equals(42));
     expect(topLevelField, equals(42));
   }));
 
-  classMirror.setFieldAsync(const Symbol('staticField'), 43);
-  future = classMirror.getFieldAsync(const Symbol('staticField'));
+  classMirror.setFieldAsync(#staticField, 43);
+  future = classMirror.getFieldAsync(#staticField);
   future.then(expectAsync1((resultMirror) {
     expect(resultMirror.reflectee, equals(43));
     expect(Class.staticField, equals(43));
   }));
 
-  instMirror.setFieldAsync(const Symbol('field'), 44);
-  future = instMirror.getFieldAsync(const Symbol('field'));
+  instMirror.setFieldAsync(#field, 44);
+  future = instMirror.getFieldAsync(#field);
   future.then(expectAsync1((resultMirror) {
     expect(resultMirror.reflectee, equals(44));
     expect(instance.field, equals(44));
@@ -173,28 +164,28 @@
   expect(instanceMirror.reflectee is Class, equals(true));
   expect(instanceMirror.reflectee.field, equals("default value"));
 
-  instanceMirror = classMirror.newInstance(const Symbol('withInitialValue'),
+  instanceMirror = classMirror.newInstance(#withInitialValue,
                                            [45]);
   expect(instanceMirror.reflectee is Class, equals(true));
   expect(instanceMirror.reflectee.field, equals(45));
 
 
-  instanceMirror = classMirror.newInstance(const Symbol('generative'),
+  instanceMirror = classMirror.newInstance(#generative,
                                            [7]);
   expect(instanceMirror.reflectee is Class, equals(true));
   expect(instanceMirror.reflectee.field, equals(7));
 
-  instanceMirror = classMirror.newInstance(const Symbol('redirecting'),
+  instanceMirror = classMirror.newInstance(#redirecting,
                                            [8]);
   expect(instanceMirror.reflectee is Class, equals(true));
   expect(instanceMirror.reflectee.field, equals(16));
 
-  instanceMirror = classMirror.newInstance(const Symbol('faktory'),
+  instanceMirror = classMirror.newInstance(#faktory,
                                            [9]);
   expect(instanceMirror.reflectee is Class, equals(true));
   expect(instanceMirror.reflectee.field, equals(27));
 
-  instanceMirror = classMirror.newInstance(const Symbol('redirectingFactory'),
+  instanceMirror = classMirror.newInstance(#redirectingFactory,
                                            [10]);
   expect(instanceMirror.reflectee is Class, equals(true));
   expect(instanceMirror.reflectee.field, equals(30));
@@ -207,7 +198,7 @@
     expect(instance.field, equals("default value"));
   }));
 
-  future = classMirror.newInstanceAsync(const Symbol('withInitialValue'), [45]);
+  future = classMirror.newInstanceAsync(#withInitialValue, [45]);
   future.then(expectAsync1((resultMirror) {
     var instance = resultMirror.reflectee;
     expect(instance is Class, equals(true));
@@ -227,39 +218,39 @@
 }
 
 testNames(mirrors) {
-  var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single;
-  var classMirror = libMirror.classes[const Symbol('Class')];
-  var typedefMirror = libMirror.members[const Symbol('Typedef')];
-  var methodMirror = libMirror.functions[const Symbol('testNames')];
-  var variableMirror = classMirror.variables[const Symbol('field')];
+  var libMirror = mirrors.findLibrary(#MirrorsTest).single;
+  var classMirror = libMirror.classes[#Class];
+  var typedefMirror = libMirror.members[#Typedef];
+  var methodMirror = libMirror.functions[#testNames];
+  var variableMirror = classMirror.variables[#field];
 
-  expect(libMirror.simpleName, equals(const Symbol('MirrorsTest')));
-  expect(libMirror.qualifiedName, equals(const Symbol('MirrorsTest')));
+  expect(libMirror.simpleName, equals(#MirrorsTest));
+  expect(libMirror.qualifiedName, equals(#MirrorsTest));
 
-  expect(classMirror.simpleName, equals(const Symbol('Class')));
-  expect(classMirror.qualifiedName, equals(const Symbol('MirrorsTest.Class')));
+  expect(classMirror.simpleName, equals(#Class));
+  expect(classMirror.qualifiedName, equals(#MirrorsTest.Class));
 
   TypeVariableMirror typeVariable = classMirror.typeVariables.single;
-  expect(typeVariable.simpleName, equals(const Symbol('T')));
+  expect(typeVariable.simpleName, equals(#T));
   expect(typeVariable.qualifiedName,
       equals(const Symbol('MirrorsTest.Class.T')));
 
   if (!isDart2js) { // TODO(ahe): Implement this in dart2js.
-    expect(typedefMirror.simpleName, equals(const Symbol('Typedef')));
+    expect(typedefMirror.simpleName, equals(#Typedef));
     expect(typedefMirror.qualifiedName,
            equals(const Symbol('MirrorsTest.Typedef')));
 
-    var typedefMirrorDeNovo = reflectClass(Typedef);
-    expect(typedefMirrorDeNovo.simpleName, equals(const Symbol('Typedef')));
+    var typedefMirrorDeNovo = reflectType(Typedef);
+    expect(typedefMirrorDeNovo.simpleName, equals(#Typedef));
     expect(typedefMirrorDeNovo.qualifiedName,
            equals(const Symbol('MirrorsTest.Typedef')));
   }
 
-  expect(methodMirror.simpleName, equals(const Symbol('testNames')));
+  expect(methodMirror.simpleName, equals(#testNames));
   expect(methodMirror.qualifiedName,
          equals(const Symbol('MirrorsTest.testNames')));
 
-  expect(variableMirror.simpleName, equals(const Symbol('field')));
+  expect(variableMirror.simpleName, equals(#field));
   expect(variableMirror.qualifiedName,
          equals(const Symbol('MirrorsTest.Class.field')));
 }
diff --git a/tests/lib/mirrors/private_symbol_test.dart b/tests/lib/mirrors/private_symbol_test.dart
index c178409..52eaa09 100644
--- a/tests/lib/mirrors/private_symbol_test.dart
+++ b/tests/lib/mirrors/private_symbol_test.dart
@@ -105,7 +105,7 @@
   Expect.equals(#_T, tvm.simpleName);
   Expect.equals('_T', MirrorSystem.getName(tvm.simpleName));
 
-  TypedefMirror tdm = reflectClass(_F);
+  TypedefMirror tdm = reflectType(_F);
   Expect.equals(#_F, tdm.simpleName);
   Expect.equals('_F', MirrorSystem.getName(tdm.simpleName));
 
diff --git a/tests/lib/mirrors/typedef_metadata_test.dart b/tests/lib/mirrors/typedef_metadata_test.dart
index 0312662..36e0837 100644
--- a/tests/lib/mirrors/typedef_metadata_test.dart
+++ b/tests/lib/mirrors/typedef_metadata_test.dart
@@ -18,6 +18,6 @@
 typedef bool Predicate(Object o);
 
 main() {
-  checkMetadata(reflectClass(MA), [symbol]);
-  checkMetadata(reflectClass(Predicate), [string]);
+  checkMetadata(reflectType(MA), [symbol]);
+  checkMetadata(reflectType(Predicate), [string]);
 }
diff --git a/tests/lib/mirrors/typedef_test.dart b/tests/lib/mirrors/typedef_test.dart
index 3a5919a..11b9e71 100644
--- a/tests/lib/mirrors/typedef_test.dart
+++ b/tests/lib/mirrors/typedef_test.dart
@@ -64,7 +64,7 @@
 TypeMirror on 'dynamic'
 []
 """,
-      check(reflectClass(Func)));
+      check(reflectType(Func)));
   Expect.stringEquals(
       """
 TypedefMirror on 'Void'
@@ -72,7 +72,7 @@
 TypeMirror on 'void'
 []
 """,
-      check(reflectClass(Void)));
+      check(reflectType(Void)));
   Expect.stringEquals(
       """
 TypedefMirror on 'Foo'
@@ -82,7 +82,7 @@
 Symbol(\"$x\")
 ClassMirror on 'int'
 """,
-      check(reflectClass(Foo)));
+      check(reflectType(Foo)));
   String type = ft('(dart.core.int, dart.core.num)', 'dart.core.String');
   Expect.stringEquals(
       """
@@ -95,7 +95,7 @@
 Symbol(\"$y\")
 ClassMirror on 'num'
 """,
-      check(reflectClass(Foo2)));
+      check(reflectType(Foo2)));
   type = ft('(dart.core.int, [dart.core.num])', 'dart.core.String');
   Expect.stringEquals(
       """
@@ -108,7 +108,7 @@
 Symbol(\"$y\")
 ClassMirror on 'num'
 """,
-      check(reflectClass(Bar)));
+      check(reflectType(Bar)));
   type = ft('(dart.core.int, [dart.core.num, dart.core.num])',
             'dart.core.String');
   Expect.stringEquals(
@@ -124,7 +124,7 @@
 Symbol(\"$z\")
 ClassMirror on 'num'
 """,
-      check(reflectClass(Bar2)));
+      check(reflectType(Bar2)));
   type = ft('(dart.core.int, {y: dart.core.num})', 'dart.core.String');
   Expect.stringEquals(
       """
@@ -137,7 +137,7 @@
 Symbol(\"y\")
 ClassMirror on 'num'
 """,
-      check(reflectClass(Baz)));
+      check(reflectType(Baz)));
   type = ft('(dart.core.int, {y: dart.core.num, z: dart.core.num})',
             'dart.core.String');
   Expect.stringEquals(
@@ -153,5 +153,5 @@
 Symbol(\"z\")
 ClassMirror on 'num'
 """,
-      check(reflectClass(Baz2)));
+      check(reflectType(Baz2)));
 }
diff --git a/tests/lib/mirrors/typevariable_mirror_metadata_test.dart b/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
index aa59870..fa05d64 100644
--- a/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
+++ b/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
@@ -12,20 +12,9 @@
 const m2 = #m2;
 const m3 = 3;
 
-class A <S, @m1 @m2 T> {
-  // TODO(13327): Remove this once the name collision is prohibited by the
-  // compiler/runtime.
-  @m3
-  T() => null;
-}
+class A <S, @m1 @m2 T> {}
 
-class B <@m3 T> {
-  // TODO(13327): Remove this once the name collision is prohibited by the
-  // compiler/runtime.
-  @m1
-  @m2
-  var T;
-}
+class B <@m3 T> {}
 
 typedef bool Predicate<@m1 @m2 G>(G a);
 
@@ -34,15 +23,13 @@
   cm = reflectClass(A);
   checkMetadata(cm.typeVariables[0], []);
   checkMetadata(cm.typeVariables[1], [m1, m2]);
-  // Check for conflicts.
-  checkMetadata(cm.methods[#T], [m3]);
 
   cm = reflectClass(B);
   checkMetadata(cm.typeVariables[0], [m3]);
-  // Check for conflicts.
-  checkMetadata(cm.members[#T], [m1, m2]);
 
-  TypedefMirror tm = reflectClass(Predicate);
-  FunctionTypeMirror ftm = tm.referent;
-  checkMetadata(ftm.typeVariables[0], [m1, m2]);
+  // Partial coverage.
+  return; /// 01: ok
+
+  TypedefMirror tm = reflectType(Predicate);
+  checkMetadata(tm.typeVariables[0], [m1, m2]);
 }
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index 3ddae2a..9859e23 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -113,7 +113,8 @@
 void testProcessQueue() {
   var maxProcesses = 2;
   var maxBrowserProcesses = maxProcesses;
-  new ProcessQueue({'noBatch' : true}, maxProcesses, maxBrowserProcesses,
+  var config = new TestOptionsParser().parse(['--nobatch'])[0];
+  new ProcessQueue(config, maxProcesses, maxBrowserProcesses,
       new DateTime.now(), [new CustomTestSuite()],
       [new EventListener()], TestController.finished);
 }
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 6a464c3..95eb2c3 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -18,3 +18,6 @@
 
 [ $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 b409bea..0375939 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 8
-BUILD 3
-PATCH 2 
+BUILD 4
+PATCH 0 
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index a1a639f..9f3bccc 100644
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -76,6 +76,7 @@
          -{linux,macos,windows}-{ia32,x64}-release.zip
     - /sdk/dartsdk-{linux,macos,windows}-{ia32,x64}-release.zip
     - /editor/darteditor-{linux,macos,windows}-{ia32,x64}.zip
+    - /editor/darteditor-installer-macos-{ia32,x64}.dmg
     - /editor-eclipse-update
          /{index.html,features/,plugins/,artifacts.jar,content.jar}
   """
@@ -98,6 +99,10 @@
     return '/'.join([self.editor_directory(revision),
       self.editor_zipfilename(system, arch)])
 
+  def editor_installer_zipfilepath(self, revision, system, arch, extension):
+    return '/'.join([self.editor_directory(revision),
+      self.editor_installer_zipfilename(system, arch, extension)])
+
   def sdk_zipfilepath(self, revision, system, arch, mode):
     return '/'.join([self.sdk_directory(revision),
       self.sdk_zipfilename(system, arch, mode)])
@@ -139,6 +144,11 @@
     return 'darteditor-%s-%s.zip' % (
         SYSTEM_RENAMES[system], ARCH_RENAMES[arch])
 
+  def editor_installer_zipfilename(self, system, arch, extension):
+    assert extension in ['dmg']
+    return 'darteditor-installer-%s-%s.%s' % (
+        SYSTEM_RENAMES[system], ARCH_RENAMES[arch], extension)
+
   def sdk_zipfilename(self, system, arch, mode):
     assert mode in Mode.ALL_MODES
     return 'dartsdk-%s-%s-%s.zip' % (
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 8ca4b5e..10bd6fc 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -137,39 +137,8 @@
         dartium_output_dir)
     cpp_library_emitter.EmitResolver(
         template_loader.Load('cpp_resolver.template'), dartium_output_dir)
-
-    path = os.path.join(cpp_output_dir, 'DartWebkitClassIds.h')
-    e = emitters.FileEmitter(path)
-    e.Emit("""
-// WARNING: Do not edit - generated code.
-// See dart/tools/dom/scripts/dartdomgenerator.py
-
-#ifndef DartWebkitClassIds_h
-#define DartWebkitClassIds_h
-
-namespace WebCore {
-
-enum {
-    _HistoryCrossFrameClassId = 0,
-    _LocationCrossFrameClassId,
-    _DOMWindowCrossFrameClassId,
-    _DateTimeClassId,
-    // New types that are not auto-generated should be added here.
-""")
-    for interface in webkit_database.GetInterfaces():
-      interface_name = interface.id
-      e.Emit('    %sClassId,\n' % interface_name)
-    e.Emit("""
-    NumWebkitClassIds
-};
-
-} // namespace WebCore
-
-#endif // DartWebkitClassIds_h
-""")
-
-  _logger.info('Flush...')
-  emitters.Flush()
+    cpp_library_emitter.EmitClassIdTable(
+        webkit_database, dartium_output_dir, type_registry, renamer)
 
   if update_dom_metadata:
     metadata.Flush()
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index c25100a..c0104c2 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -56,7 +56,7 @@
       "@Returns('String|CanvasGradient|CanvasPattern')",
     ],
 
-    'CustomEvent.detail': [
+    'CustomEvent._detail': [
       "@Creates('Null')",
     ],
 
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 8243241..eb1539e 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -92,6 +92,7 @@
     # T and no other browser has tag T).
 
     'AnalyserNode': 'AnalyserNode,RealtimeAnalyserNode',
+    'AudioContext': 'AudioContext,webkitAudioContext',
 
     'ChannelMergerNode': 'ChannelMergerNode,AudioChannelMerger',
     'ChannelSplitterNode': 'ChannelSplitterNode,AudioChannelSplitter',
@@ -794,6 +795,9 @@
   def __init__(self, idl_type, data):
     super(CallbackIDLTypeInfo, self).__init__(idl_type, data)
 
+  def implementation_name(self):
+    return ""
+
 
 def array_type(data_type):
   matched = re.match(r'([\w\d_\s]+)\[\]', data_type)
@@ -858,6 +862,9 @@
 
   def pass_native_by_ref(self): return False
 
+  def implementation_name(self):
+    return ""
+
 
 class PrimitiveIDLTypeInfo(IDLTypeInfo):
   def __init__(self, idl_type, data):
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 69023dd..3d9f5a0 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -356,7 +356,6 @@
     'Node.appendChild': 'append',
     'Node.cloneNode': 'clone',
     'Node.nextSibling': 'nextNode',
-    'Node.ownerDocument': 'document',
     'Node.parentElement': 'parent',
     'Node.previousSibling': 'previousNode',
     'Node.textContent': 'text',
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 2e74ab7..5aa06ee 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -224,7 +224,7 @@
     return template
 
   def RootClassName(self):
-    return 'NativeFieldWrapperClass1'
+    return 'NativeFieldWrapperClass2'
 
   def NativeSpec(self):
     return ''
@@ -554,7 +554,7 @@
         'void',
         False,
         'SetterRaisesException' in attr.ext_attrs,
-        requires_custom_element_callback=True)
+        generate_custom_element_scope_if_needed=True)
 
   def AddIndexer(self, element_type):
     """Adds all the methods required to complete implementation of List."""
@@ -723,7 +723,8 @@
         arguments,
         operation.type.id,
         operation.type.nullable,
-        'RaisesException' in operation.ext_attrs)
+        'RaisesException' in operation.ext_attrs,
+        generate_custom_element_scope_if_needed=True)
 
   def _GenerateNativeCallback(self,
       callback_name,
@@ -734,7 +735,7 @@
       return_type,
       return_type_is_nullable,
       raises_dom_exception,
-      requires_custom_element_callback=False):
+      generate_custom_element_scope_if_needed=False):
 
     ext_attrs = node.ext_attrs
 
@@ -793,7 +794,7 @@
     if 'Reflect' in ext_attrs:
       cpp_arguments = [self._GenerateWebCoreReflectionAttributeName(node)]
 
-    if ext_attrs.get('CustomElementCallbacks') == 'Enable' or requires_custom_element_callback:
+    if generate_custom_element_scope_if_needed and (ext_attrs.get('CustomElementCallbacks', 'None') != 'None' or 'Reflect' in ext_attrs):
       self._cpp_impl_includes.add('"core/dom/CustomElementCallbackDispatcher.h"')
       needs_custom_element_callbacks = True
 
@@ -1184,6 +1185,101 @@
             '        return func;\n',
             CLASS_NAME=os.path.splitext(os.path.basename(path))[0])
 
+  def EmitClassIdTable(self, database, output_dir, type_registry, renamer):
+    path = os.path.join(output_dir, 'DartWebkitClassIds.h')
+    e = self._emitters.FileEmitter(path)
+    e.Emit('// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file\n');
+    e.Emit('// for details. All rights reserved. Use of this source code is governed by a\n');
+    e.Emit('// BSD-style license that can be found in the LICENSE file.\n');
+    e.Emit('// WARNING: Do not edit - generated code.\n');
+    e.Emit('// See dart/tools/dom/scripts/systemnative.py\n');
+    e.Emit('\n');
+    e.Emit('#ifndef DartWebkitClassIds_h\n');
+    e.Emit('#define DartWebkitClassIds_h\n');
+    e.Emit('\n');
+    e.Emit('namespace WebCore {\n');
+    e.Emit('\n');
+    e.Emit('enum {\n');
+    e.Emit('    _InvalidClassId = 0,\n');
+    e.Emit('    _HistoryCrossFrameClassId,\n');
+    e.Emit('    _LocationCrossFrameClassId,\n');
+    e.Emit('    _DOMWindowCrossFrameClassId,\n');
+    e.Emit('    _DateTimeClassId,\n');
+    e.Emit('    _JsObjectClassId,\n');
+    e.Emit('    _JsFunctionClassId,\n');
+    e.Emit('    // New types that are not auto-generated should be added here.\n');
+    e.Emit('\n');
+    for interface in database.GetInterfaces():
+      interface_name = interface.id
+      e.Emit('    %sClassId,\n' % interface_name)
+    e.Emit('    NumWebkitClassIds\n');
+    e.Emit('};\n');
+
+    e.Emit('typedef struct {\n');
+    e.Emit('    const char* class_name;\n');
+    e.Emit('    int library_id;\n');
+    e.Emit('    int base_class_id;\n');
+    e.Emit('    bool is_node;\n');
+    e.Emit('    bool is_active;\n');
+    e.Emit('    bool is_event;\n');
+    e.Emit('} _Classinfo;\n');
+    e.Emit('typedef _Classinfo _DartWebkitClassInfo[NumWebkitClassIds];\n');
+    e.Emit('\n');
+    e.Emit('extern _DartWebkitClassInfo DartWebkitClassInfo;\n');
+    e.Emit('\n');
+    e.Emit('} // namespace WebCore\n');
+    e.Emit('#endif // DartWebkitClassIds_h\n');
+    self._emitters.Flush()
+
+    path = os.path.join(output_dir, 'DartWebkitClassIds.cpp')
+    e = self._emitters.FileEmitter(path)
+    e.Emit('// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file\n');
+    e.Emit('// for details. All rights reserved. Use of this source code is governed by a\n');
+    e.Emit('// BSD-style license that can be found in the LICENSE file.\n');
+    e.Emit('// WARNING: Do not edit - generated code.\n');
+    e.Emit('// See dart/tools/dom/scripts/systemnative.py\n');
+    e.Emit('\n');
+    e.Emit('#include "DartWebkitClassIds.h"\n');
+    e.Emit('\n');
+    e.Emit('#include "bindings/dart/DartLibraryIds.h"\n');
+    e.Emit('\n');
+    e.Emit('namespace WebCore {\n');
+    e.Emit('\n');
+    e.Emit("_DartWebkitClassInfo DartWebkitClassInfo = {\n");
+    e.Emit('    { "_InvalidClassId", -1, -1, false, false, false },\n');
+    e.Emit('    { "_HistoryCrossFrame", DartHtmlLibraryId, -1, false, false, false },\n');
+    e.Emit('    { "_LocationCrossFrame", DartHtmlLibraryId, -1, false, false, false },\n');
+    e.Emit('    { "_DOMWindowCrossFrame", DartHtmlLibraryId, -1, false, false, true },\n');
+    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('    // New types that are not auto-generated should be added here.\n');
+    e.Emit('\n');
+    is_node_test = lambda interface: interface.id == 'Node'
+    is_active_test = lambda interface: 'ActiveDOMObject' in interface.ext_attrs
+    is_event_target_test = lambda interface: 'EventTarget' in interface.ext_attrs
+    def TypeCheckHelper(test):
+      return 'true' if any(map(test, database.Hierarchy(interface))) else 'false'
+    for interface in database.GetInterfaces():
+      e.Emit("    {")
+      type_info = type_registry.TypeInfo(interface.id)
+      type_info.native_type().replace('<', '_').replace('>', '_'),
+      e.Emit(' "%s",' % type_info.implementation_name())
+      e.Emit(' Dart%sLibraryId,' % renamer.GetLibraryId(interface))
+      if interface.parents:
+        supertype = interface.parents[0].type.id
+        e.Emit(' %sClassId,\n' % supertype)
+      else:
+        e.Emit(' -1,')
+      e.Emit(" %s," % TypeCheckHelper(is_node_test))
+      e.Emit(" %s," % TypeCheckHelper(is_active_test))
+      e.Emit(" %s," % TypeCheckHelper(is_event_target_test))
+      e.Emit(" },\n")
+    e.Emit("};\n");
+    e.Emit('\n');
+    e.Emit('} // namespace WebCore\n');
+    self._emitters.Flush()
+
 def _IsOptionalStringArgumentInInitEventMethod(interface, operation, argument):
   return (
       interface.id.endswith('Event') and
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 58c1d6a..5d9a910 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -35,8 +35,13 @@
    *
    * This is the Dart equivalent of jQuery's
    * [addClass](http://api.jquery.com/addClass/).
+   *
+   * If this corresponds to one element. Returns `true` if [value] was added to
+   * the set, otherwise `false`.
+   *
+   * If this corresponds to many elements, `null` is always returned.
    */
-  void add(String value);
+  bool add(String value);
 
   /**
    * Remove the class [value] from element, and return true on successful
@@ -111,7 +116,7 @@
    *   After f returns, the modified set is written to the
    *       className property of this element.
    */
-  void modify( f(Set<String> s)) {
+  modify( f(Set<String> s)) {
     _elementCssClassSetIterable.forEach((e) => e.modify(f));
   }
 
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index eef7ebd..58c6cde 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -40,6 +40,8 @@
    * [delegate](http://api.jquery.com/delegate/).
    */
   Stream<T> matches(String selector);
+
+  StreamSubscription<T> capture(void onData(T event));
 }
 
 /**
@@ -56,6 +58,10 @@
         e._selector = selector;
         return e;
       });
+
+  StreamSubscription<T> capture(void onData(T event)) =>
+    new _EventStreamSubscription<T>(
+        this._target, this._eventType, onData, true);
 }
 
 /**
@@ -64,17 +70,12 @@
  */
 class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
     implements ElementStream<T> {
-  final _StreamPool _pool;
-  Stream<T> _stream;
+  final Iterable<Element> _targetList;
+  final bool _useCapture;
+  final String _eventType;
 
-  _ElementListEventStreamImpl(targetList, eventType, useCapture) :
-      _pool = new _StreamPool.broadcast() {
-    for (Element target in targetList) {
-      var stream = new _EventStream(target, eventType, useCapture);
-      _pool.add(stream);
-    }
-    _stream = _pool.stream;
-  }
+  _ElementListEventStreamImpl(
+      this._targetList, this._eventType, this._useCapture);
 
   Stream<T> matches(String selector) => this.where(
       (event) => event.target.matchesWithAncestors(selector)).map((e) {
@@ -82,16 +83,30 @@
         return e;
       });
 
-  // Delegate all regular Stream behavor to our wrapped Stream.
+  // Delegate all regular Stream behavior to a wrapped Stream.
   StreamSubscription<T> listen(void onData(T event),
       { Function onError,
         void onDone(),
-        bool cancelOnError}) =>
-      _stream.listen(onData, onError: onError, onDone: onDone,
+        bool cancelOnError}) {
+    var pool = new _StreamPool.broadcast();
+    for (var target in _targetList) {
+      pool.add(new _EventStream(target, _eventType, _useCapture));
+    }
+    return pool.stream.listen(onData, onError: onError, onDone: onDone,
           cancelOnError: cancelOnError);
+  }
+
+  StreamSubscription<T> capture(void onData(T event)) {
+    var pool = new _StreamPool.broadcast();
+    for (var target in _targetList) {
+      pool.add(new _EventStream(target, _eventType, true));
+    }
+    return pool.stream.listen(onData);
+  }
+
   Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
                                void onCancel(StreamSubscription subscription)})
-      => _stream;
+      => this;
   bool get isBroadcast => true;
 }
 
diff --git a/tools/dom/src/dart2js_CustomElementSupport.dart b/tools/dom/src/dart2js_CustomElementSupport.dart
index 8edecc4..6f8aedb 100644
--- a/tools/dom/src/dart2js_CustomElementSupport.dart
+++ b/tools/dom/src/dart2js_CustomElementSupport.dart
@@ -41,30 +41,6 @@
       convertDartClosureToJS(callback, 4));
 }
 
-const _typeNameToTag = const {
-  'HTMLAnchorElement': 'a',
-  'HTMLAudioElement': 'audio',
-  'HTMLButtonElement': 'button',
-  'HTMLCanvasElement': 'canvas',
-  'HTMLDivElement': 'div',
-  'HTMLImageElement': 'img',
-  'HTMLInputElement': 'input',
-  'HTMLLIElement': 'li',
-  'HTMLLabelElement': 'label',
-  'HTMLMenuElement': 'menu',
-  'HTMLMeterElement': 'meter',
-  'HTMLOListElement': 'ol',
-  'HTMLOptionElement': 'option',
-  'HTMLOutputElement': 'output',
-  'HTMLParagraphElement': 'p',
-  'HTMLPreElement': 'pre',
-  'HTMLProgressElement': 'progress',
-  'HTMLSelectElement': 'select',
-  'HTMLSpanElement': 'span',
-  'HTMLUListElement': 'ul',
-  'HTMLVideoElement': 'video',
-};
-
 void _registerCustomElement(context, document, String tag, Type type,
     String extendsTagName) {
   // Function follows the same pattern as the following JavaScript code for
@@ -133,8 +109,6 @@
   if (baseClassName != 'HTMLElement') {
     if (extendsTagName != null) {
       JS('=Object', '#.extends = #', options, extendsTagName);
-    } else if (_typeNameToTag.containsKey(baseClassName)) {
-      JS('=Object', '#.extends = #', options, _typeNameToTag[baseClassName]);
     }
   }
 
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 7b12348..e650c6f 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -87,6 +87,8 @@
 
   static bool isMap(obj) => obj is Map;
 
+  static List toListIfIterable(obj) => obj is Iterable ? obj.toList() : null;
+
   static Map createMap() => {};
 
   static makeUnimplementedError(String fileName, int lineNo) {
@@ -104,9 +106,12 @@
     return false;
   }
 
-  static bool isTypeSubclassOfTag(Type type, String tagName) {
+  static Element getAndValidateNativeType(Type type, String tagName) {
     var element = new Element.tag(tagName);
-    return isTypeSubclassOf(type, element.runtimeType);
+    if (!isTypeSubclassOf(type, element.runtimeType)) {
+      return null;
+    }
+    return element;
   }
 
   static window() native "Utils_window";
@@ -390,10 +395,6 @@
 
   static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
 
-  // TODO(jacobr): we need a failsafe way to determine that a Node is really a
-  // DOM node rather than just a class that extends Node.
-  static bool isNode(obj) => obj is Node;
-
   static bool _isBuiltinType(ClassMirror cls) {
     // TODO(vsm): Find a less hackish way to do this.
     LibraryMirror lib = cls.owner;
@@ -423,7 +424,7 @@
   static void initializeCustomElement(HtmlElement element) native "Utils_initializeCustomElement";
 }
 
-class _DOMWindowCrossFrame extends NativeFieldWrapperClass1 implements
+class _DOMWindowCrossFrame extends NativeFieldWrapperClass2 implements
     WindowBase {
   _DOMWindowCrossFrame.internal();
 
@@ -444,7 +445,7 @@
   String get typeName => "Window";
 }
 
-class _HistoryCrossFrame extends NativeFieldWrapperClass1 implements HistoryBase {
+class _HistoryCrossFrame extends NativeFieldWrapperClass2 implements HistoryBase {
   _HistoryCrossFrame.internal();
 
   // Methods.
@@ -456,7 +457,7 @@
   String get typeName => "History";
 }
 
-class _LocationCrossFrame extends NativeFieldWrapperClass1 implements LocationBase {
+class _LocationCrossFrame extends NativeFieldWrapperClass2 implements LocationBase {
   _LocationCrossFrame.internal();
 
   // Fields.
@@ -466,7 +467,7 @@
   String get typeName => "Location";
 }
 
-class _DOMStringMap extends NativeFieldWrapperClass1 implements Map<String, String> {
+class _DOMStringMap extends NativeFieldWrapperClass2 implements Map<String, String> {
   _DOMStringMap.internal();
 
   bool containsValue(String value) => Maps.containsValue(this, value);
@@ -537,10 +538,14 @@
   Function _callback;
 
   _ScheduleImmediateHelper() {
-    // Mutation events get fired as soon as the current event stack is unwound
-    // so we just make a dummy event and listen for that.
-    _observer = new MutationObserver(_handleMutation);
-    _observer.observe(_div, attributes: true);
+    // Run in the root-zone as the DOM callback would otherwise execute in the
+    // current zone.
+    Zone.ROOT.run(() {
+      // Mutation events get fired as soon as the current event stack is unwound
+      // so we just make a dummy event and listen for that.
+      _observer = new MutationObserver(_handleMutation);
+      _observer.observe(_div, attributes: true);
+    });
   }
 
   void _schedule(callback) {
diff --git a/tools/dom/templates/html/impl/impl_Document.darttemplate b/tools/dom/templates/html/impl/impl_Document.darttemplate
index 47867a8..32ec467 100644
--- a/tools/dom/templates/html/impl/impl_Document.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Document.darttemplate
@@ -4,7 +4,7 @@
 
 part of $LIBRARYNAME;
 
-@DocsEditable
+@DocsEditable()
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME extends Node $NATIVESPEC
 {
 
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 1cf653d..4f4241e 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -309,7 +309,7 @@
 $!ELEMENT_STREAM_GETTERS
 }
 
-@DocsEditable
+@DocsEditable()
 $(ANNOTATIONS)abstract class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
 
   /**
@@ -584,7 +584,7 @@
   ElementList querySelectorAll(String selectors) =>
     new _FrozenElementList._wrap(_querySelectorAll(selectors));
 
-  /** 
+  /**
    * Alias for [querySelector]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -593,7 +593,7 @@
   @Experimental()
   Element query(String relativeSelectors) => querySelector(relativeSelectors);
 
-  /** 
+  /**
    * Alias for [querySelectorAll]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -1329,6 +1329,9 @@
     }
 
     treeSanitizer.sanitizeTree(fragment);
+    // Copy the fragment over to the main document (fix for 14184)
+    document.adoptNode(fragment);
+
     return fragment;
   }
 
@@ -1380,6 +1383,12 @@
     _innerHtml = html;
   }
 
+  /**
+   * This is an ease-of-use accessor for event streams which should only be
+   * used when an explicit accessor is not available.
+   */
+  ElementEvents get on => new ElementEvents(this);
+
 $!MEMBERS
 }
 
diff --git a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
index 06b24fb..1630878 100644
--- a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
+++ b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
@@ -51,6 +51,17 @@
   }
 }
 
+class ElementEvents extends Events {
+  /* Raw event target. */
+  final Element _ptr;
+
+  ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
+
+  Stream operator [](String type) {
+    return new _ElementEventStreamImpl(_ptr, type, false);
+  }
+}
+
 /**
  * Base class for all browser objects that support events.
  *
diff --git a/tools/dom/templates/html/impl/impl_HTMLOptionElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLOptionElement.darttemplate
index b40c7be..24e2985 100644
--- a/tools/dom/templates/html/impl/impl_HTMLOptionElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLOptionElement.darttemplate
@@ -5,9 +5,8 @@
 part of $LIBRARYNAME;
 
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
-  factory OptionElement({String data, String value, bool defaultSelected, 
-      bool selected}) {
-    return new OptionElement._(data, value, defaultSelected, selected);
+  factory OptionElement({String data, String value, bool selected: false}) {
+    return new OptionElement._(data, value, false, selected);
   }
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
index c176c5f..1ba903c 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
@@ -254,7 +254,7 @@
     // Need to do this first as the contents may get lifted if |node| is
     // template.
     // TODO(jmesserly): content is DocumentFragment or Element
-    var descendents = 
+    var descendents =
         (content as dynamic).querySelectorAll(_allTemplatesSelectors);
     if (content is Element && (content as Element).isTemplate) {
       _bootstrap(content);
diff --git a/tools/dom/templates/html/impl/impl_IDBTransaction.darttemplate b/tools/dom/templates/html/impl/impl_IDBTransaction.darttemplate
index 180b2b0..39133b0 100644
--- a/tools/dom/templates/html/impl/impl_IDBTransaction.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBTransaction.darttemplate
@@ -25,7 +25,10 @@
     });
 
     this.onAbort.first.then((e) {
-      completer.completeError(e);
+      // Avoid completing twice if an error occurs.
+      if (!completer.isCompleted) {
+        completer.completeError(e);
+      }
     });
 
     return completer.future;
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 6d4eca6..7fa868c 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -325,5 +325,12 @@
   TemplateInstance get templateInstance =>
       TemplateElement.mdvPackage(this).templateInstance;
 
+
+  /**
+   * Use ownerDocument instead.
+   */
+  @deprecated
+  Document get document => ownerDocument;
+
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index c8f32e0..7874d5c 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -4,7 +4,7 @@
 
 part of $LIBRARYNAME;
 
-@DocsEditable
+@DocsEditable()
 $if DART2JS
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS native "Window,DOMWindow" {
 $else
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 533265e..524b928 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -54,8 +54,8 @@
   /**
    * Makes a server POST request with the specified data encoded as form data.
    *
-   * This is roughly the POST equivalent of getString. This method is similar 
-   * to sending a FormData object with broader browser support but limited to 
+   * This is roughly the POST equivalent of getString. This method is similar
+   * to sending a FormData object with broader browser support but limited to
    * String values.
    *
    * See also:
@@ -90,7 +90,7 @@
    * Creates and sends a URL request for the specified [url].
    *
    * By default `request` will perform an HTTP GET request, but a different
-   * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the 
+   * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
    * [method] parameter.
    *
    * The Future is completed when the response is available.
@@ -270,5 +270,41 @@
 $endif
   }
 
+  /**
+   * Returns all response headers as a key-value map.
+   *
+   * Multiple values for the same header key can be combined into one,
+   * separated by a comma and a space.
+   *
+   * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
+   */
+  Map<String, String> get responseHeaders {
+    // from Closure's goog.net.Xhrio.getResponseHeaders.
+    var headers = <String, String>{};
+    var headersString = this.getAllResponseHeaders();
+    if (headersString == null) {
+      return headers;
+    }
+    var headersList = headersString.split('\r\n');
+    for (var header in headersList) {
+      if (header.isEmpty) {
+        continue;
+      }
+
+      var splitIdx = header.indexOf(': ');
+      if (splitIdx == -1) {
+        continue;
+      }
+      var key = header.substring(0, splitIdx).toLowerCase();
+      var value = header.substring(splitIdx + 2);
+      if (headers.containsKey(key)) {
+        headers[key] = '${headers[key]}, $value';
+      } else {
+        headers[key] = value;
+      }
+    }
+    return headers;
+  }
+
 $!MEMBERS
 }
diff --git a/tools/mac_build_editor_dmg.sh b/tools/mac_build_editor_dmg.sh
index 2da8c0f..15b70e1 100755
--- a/tools/mac_build_editor_dmg.sh
+++ b/tools/mac_build_editor_dmg.sh
@@ -9,29 +9,26 @@
 
 # Fail if a command failed
 set -e
+set -o errexit
+set -o nounset
 
 if [ $# -ne 4 ]; then
-  echo "Usage $0 <output.dmg> <app-folder> <icon.icns> <volume-name>"
+  echo "Usage $0 <output.dmg> <raw-editor-bundle> <folder-icon> <volume-name>"
   exit 1
 fi
 
 OUTPUT_DMG_FILE=$1
-INPUT_APP_FOLDER_PATH=$2
-INPUT_ICON=$3
+INPUT_FOLDER_PATH=$2
+FOLDER_ICON=$3
 INPUT_VOLUME_NAME=$4
 
-APP_FOLDER_NAME=$(basename "$INPUT_APP_FOLDER_PATH")
+FOLDER_NAME="Dart"
 VOLUME_MOUNTPOINT="/Volumes/$INPUT_VOLUME_NAME"
 SPARSEIMAGE="$OUTPUT_DMG_FILE.sparseimage"
 
 # Input validations
-if [ "${INPUT_APP_FOLDER_PATH##*.}" != "app" ]; then
-  echo "Application folder has to end in '.app' " \
-       "(but was $INPUT_APP_FOLDER_PATH)."
-  exit 1
-fi
-if [ "${INPUT_ICON##*.}" != "icns" ]; then
-  echo "Volume icon has to end in '.icns'."
+if [ ! -d "$INPUT_FOLDER_PATH" ]; then
+  echo "Editor bundle folder does not exist ($INPUT_FOLDER_PATH)"
   exit 1
 fi
 
@@ -48,43 +45,75 @@
   rm "$OUTPUT_DMG_FILE"
 fi
 
+# This function will set (or replace) the icon of a folder.
+# Finder displays a default folder icon. Since the installer
+# will consist of a folder and a link to "/Applications", we want
+# the folder to have a nice icon.
+# In order to make Finder display a custom icon, we need to
+#  - Have a "FOLDER/Icon\r" file which contains the icon resource
+#    (i.e. the metadata of this file will contain an icon)
+#  - Have the 'custom icon' attribute set on "FOLDER"
+# Additionally we mark the "FOLDER/Icon\r" file as invisible, so it
+# is not shown in Finder (although it's visible on the commandline).
+replace_folder_icon() {
+  FOLDER="$1"
+  ICON="$2"
+  TEMP_ICON_RESOURCE='/tmp/icns.rsrc'
+  ICON_RESOURCE="$FOLDER"/$'Icon\r'
+
+  # Add finder icon to the image file
+  sips -i "$ICON" > /dev/null
+
+  # Extract the finder icon resource
+  DeRez -only icns "$ICON" > "$TEMP_ICON_RESOURCE"
+
+  # Create the icon resource
+  rm -f "$ICON_RESOURCE"
+  Rez -append "$TEMP_ICON_RESOURCE" -o "$ICON_RESOURCE"
+  rm "$TEMP_ICON_RESOURCE"
+
+  # Set the 'custom icon' attribute on $FOLDER
+  SetFile -a C "$FOLDER"
+
+  # Make the $ICON_RESOURCE invisible for finder
+  SetFile -a V "$ICON_RESOURCE"
+}
+
+
 # Create a new image and attach it
-hdiutil create -size 300m -type SPARSE -volname "$INPUT_VOLUME_NAME" -fs \
+hdiutil create -size 400m -type SPARSE -volname "$INPUT_VOLUME_NAME" -fs \
   'Journaled HFS+' "$SPARSEIMAGE"
 hdiutil attach "$SPARSEIMAGE"
 
 # Add link to /Applications (so the user can drag-and-drop into it)
 ln -s /Applications "$VOLUME_MOUNTPOINT/"
 # Copy our application
-ditto "$INPUT_APP_FOLDER_PATH" "$VOLUME_MOUNTPOINT/$APP_FOLDER_NAME"
-# Make sure that the folder gets opened when mounting the image
+ditto "$INPUT_FOLDER_PATH" "$VOLUME_MOUNTPOINT/$FOLDER_NAME"
+# Set custom icon on this folder
+replace_folder_icon "$VOLUME_MOUNTPOINT/$FOLDER_NAME" "$FOLDER_ICON"
+# Make sure that the dmg gets opened when mounting the image
 bless --folder "$VOLUME_MOUNTPOINT" --openfolder "$VOLUME_MOUNTPOINT"
-# Copy the volume icon
-cp "$INPUT_ICON" "$VOLUME_MOUNTPOINT/.VolumeIcon.icns"
-
-# Set the 'custom-icon' attribute on the volume
-SetFile -a C "$VOLUME_MOUNTPOINT"
 
 # Use an applescript to setup the layout of the folder.
 osascript << EOF
 tell application "Finder"
-	tell disk "$INPUT_VOLUME_NAME"
-		open
-		tell container window
-			set current view to icon view
-			set toolbar visible to false
-			set statusbar visible to false
-			set position to {100, 100}
-			set bounds to {100, 100, 512, 256}
-		end tell
-		tell icon view options of container window
-			set arrangement to not arranged
-			set icon size to 128
-		end tell
-		set position of item "$APP_FOLDER_NAME" to {64, 64}
-		set position of item "Applications" to {320, 64}
+  tell disk "$INPUT_VOLUME_NAME"
+    open
+    tell container window
+      set current view to icon view
+      set toolbar visible to false
+      set statusbar visible to false
+      set position to {100, 100}
+      set bounds to {100, 100, 512, 256}
+    end tell
+    tell icon view options of container window
+      set arrangement to not arranged
+      set icon size to 128
+    end tell
+    set position of item "$FOLDER_NAME" to {64, 64}
+    set position of item "Applications" to {320, 64}
     eject
-	end tell
+  end tell
 end tell
 EOF
 
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index d8ef891..4c1043f 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -11,11 +11,17 @@
 import 'android.dart';
 import 'utils.dart';
 
+class BrowserOutput {
+  final StringBuffer stdout = new StringBuffer();
+  final StringBuffer stderr = new StringBuffer();
+  final StringBuffer eventLog = new StringBuffer();
+}
+
 /** Class describing the interface for communicating with browsers. */
 abstract class Browser {
-  StringBuffer _stdout = new StringBuffer();
-  StringBuffer _stderr = new StringBuffer();
-  StringBuffer _usageLog = new StringBuffer();
+  BrowserOutput _allBrowserOutput = new BrowserOutput();
+  BrowserOutput _testBrowserOutput = new BrowserOutput();
+
   // This is called after the process is closed, before the done future
   // is completed.
   // Subclasses can use this to cleanup any browser specific resources
@@ -79,17 +85,23 @@
     String toLog = "$this ($id) - $event \n";
     if (debugPrint) print("usageLog: $toLog");
     if (logger != null) logger(toLog);
-    _usageLog.write(toLog);
+
+    _allBrowserOutput.eventLog.write(toLog);
+    _testBrowserOutput.eventLog.write(toLog);
   }
 
   void _addStdout(String output) {
     if (debugPrint) print("stdout: $output");
-    _stdout.write(output);
+
+    _allBrowserOutput.stdout.write(output);
+    _testBrowserOutput.stdout.write(output);
   }
 
   void _addStderr(String output) {
     if (debugPrint) print("stderr: $output");
-    _stderr.write(output);
+
+    _allBrowserOutput.stderr.write(output);
+    _testBrowserOutput.stderr.write(output);
   }
 
   Future close() {
@@ -164,13 +176,17 @@
   }
 
   /**
-   * Get any stdout that the browser wrote during execution.
+   * Get the output that was written so far to stdout/stderr/eventLog.
    */
-  String get stdout => _stdout.toString();
-  String get stderr => _stderr.toString();
-  String get usageLog => _usageLog.toString();
+  BrowserOutput get allBrowserOutput => _allBrowserOutput;
+  BrowserOutput get testBrowserOutput => _testBrowserOutput;
+
+  void resetTestBrowserOutput() {
+    _testBrowserOutput = new BrowserOutput();
+  }
 
   String toString();
+
   /** Starts the browser loading the given url */
   Future<bool> start(String url);
 }
@@ -523,7 +539,7 @@
   static const String disableScriptTimeLimit =
       'user_pref("dom.max_script_run_time", 0);';
 
-  static string _binary = _getBinary();
+  static String _binary = _getBinary();
 
   Future _createPreferenceFile(var path) {
     var file = new File("${path.toString()}/user.js");
@@ -551,7 +567,7 @@
     return Process.run(_binary, ["--version"]).then((var versionResult) {
       if (versionResult.exitCode != 0) {
         _logEvent("Failed to firefox get version");
-        _logEvent("Make sure $binary is a valid program for running firefox");
+        _logEvent("Make sure $_binary is a valid program for running firefox");
         return new Future.value(false);
       }
       version = versionResult.stdout;
@@ -566,7 +582,7 @@
 
       });
     }).catchError((e) {
-      _logEvent("Running $binary --version failed with $e");
+      _logEvent("Running $_binary --version failed with $e");
       return false;
     });
   }
@@ -620,6 +636,18 @@
   }
 }
 
+/* Describes the output of running the test in a browser */
+class BrowserTestOutput {
+  final bool didTimeout;
+  final Duration delayUntilTestStarted;
+  final Duration duration;
+  final BrowserOutput browserOutput;
+  final String dom;
+
+  BrowserTestOutput(
+      this.delayUntilTestStarted, this.duration, this.dom,
+      this.browserOutput, {this.didTimeout: false});
+}
 
 /**
  * Encapsulates all the functionality for running tests in browsers.
@@ -750,9 +778,15 @@
       }
       testCache[testId] = status.currentTest.url;
       Stopwatch watch = new Stopwatch()..start();
-      status.currentTest.doneCallback(output,
-                                      status.currentTest.delayUntilTestStarted,
-                                      status.currentTest.stopwatch.elapsed);
+
+      // Report that the test is finished now
+      var browserTestOutput = new BrowserTestOutput(
+          status.currentTest.delayUntilTestStarted,
+          status.currentTest.stopwatch.elapsed,
+          output,
+          status.browser.testBrowserOutput);
+      status.currentTest.doneCallback(browserTestOutput);
+
       watch.stop();
       status.lastTest = status.currentTest;
       status.currentTest = null;
@@ -784,7 +818,21 @@
     status.timeout = true;
     timedOut.add(status.currentTest.url);
     var id = status.browser.id;
+
+    status.currentTest.stopwatch.stop();
     status.browser.close().then((_) {
+      // Wait until the browser is closed before reporting the test as timeout.
+      // This will enable us to capture stdout/stderr from the browser
+      // (which might provide us with information about what went wrong).
+      var browserTestOutput = new BrowserTestOutput(
+          status.currentTest.delayUntilTestStarted,
+          status.currentTest.stopwatch.elapsed,
+          'Dom could not be fetched, since the test timed out.',
+          status.browser.testBrowserOutput,
+          didTimeout: true);
+      status.currentTest.doneCallback(browserTestOutput);
+      status.currentTest = null;
+
       // We don't want to start a new browser if we are terminating.
       if (underTermination) return;
       var browser;
@@ -819,11 +867,6 @@
         }
       });
     });
-    status.currentTest.stopwatch.stop();
-    status.currentTest.doneCallback("TIMEOUT",
-                                    status.currentTest.delayUntilTestStarted,
-                                    status.currentTest.stopwatch.elapsed);
-    status.currentTest = null;
   }
 
   BrowserTest getNextTest(String browserId) {
@@ -833,6 +876,7 @@
 
     // We are currently terminating this browser, don't start a new test.
     if (status.timeout) return null;
+
     BrowserTest test = testQueue.removeLast();
     if (status.currentTest == null) {
       status.currentTest = test;
@@ -850,6 +894,11 @@
 
     status.currentTest.timeoutTimer = createTimeoutTimer(test, status);
     status.currentTest.stopwatch = new Stopwatch()..start();
+
+    // Reset the test specific output information (stdout, stderr) on the
+    // browser since a new test is begin started.
+    status.browser.resetTestBrowserOutput();
+
     return test;
   }
 
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index d081f62..0bb1fa0 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -17,11 +17,9 @@
 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow
 // CommandOutput.exitCode in subclasses of CommandOutput.
 import "dart:io" as io;
-import "dart:isolate";
 import "dart:math" as math;
 import 'dependency_graph.dart' as dgraph;
 import "browser_controller.dart";
-import "http_server.dart" as http_server;
 import "status_file_parser.dart";
 import "test_progress.dart";
 import "test_suite.dart";
@@ -1994,25 +1992,30 @@
       BrowserTestCommand browserCommand, int timeout) {
     var completer = new Completer<CommandOutput>();
 
-    var callback = (output, delayUntilTestStarted, duration) {
-      bool timedOut = output == "TIMEOUT";
+    var callback = (BrowserTestOutput output) {
+      bool timedOut = output.didTimeout;
       String stderr = "";
       if (timedOut) {
-        if (delayUntilTestStarted != null) {
-          stderr = "This test timed out. The delay until the test was actually "
-                   "started was: $delayUntilTestStarted.";
+        if (output.delayUntilTestStarted != null) {
+          stderr = "This test timed out. The delay until the test actually "
+                   "started was: ${output.delayUntilTestStarted}.";
         } else {
           stderr = "This test has not notified test.py that it started running."
                    " This could be a bug in test.py! "
                    "Please contact ricow/kustermann";
         }
       }
+      stderr =
+          '$stderr\n\n'
+          'BrowserOutput while running the test (* EXPERIMENTAL *):\n'
+          'BrowserOutput.stdout:\n${output.browserOutput.stdout.toString()}\n'
+          'BrowserOutput.stderr:\n${output.browserOutput.stderr.toString()}\n';
       var commandOutput = createCommandOutput(browserCommand,
                           0,
                           timedOut,
-                          encodeUtf8(output),
+                          encodeUtf8(output.dom),
                           encodeUtf8(stderr),
-                          duration,
+                          output.duration,
                           false);
       completer.complete(commandOutput);
     };
@@ -2255,56 +2258,81 @@
                 this._listTests = false,
                 String recordingOutputFile,
                 String recordedInputFile]) {
-    bool recording = recordingOutputFile != null;
-    bool replaying = recordedInputFile != null;
+    void setupForListing(TestCaseEnqueuer testCaseEnqueuer) {
+      _graph.events.where((event) => event is dgraph.GraphSealedEvent)
+        .listen((dgraph.GraphSealedEvent event) {
+          var testCases = new List.from(testCaseEnqueuer.remainingTestCases);
+          testCases.sort((a, b) => a.displayName.compareTo(b.displayName));
 
-    // When the graph building is finished, notify event listeners.
-    _graph.events
-      .where((event) => event is dgraph.GraphSealedEvent).listen((event) {
-        eventAllTestsKnown();
-    });
+          print("\nGenerating all matching test cases ....\n");
+
+          for (TestCase testCase in testCases) {
+            print("${testCase.displayName}   "
+                  "Expectations: ${testCase.expectedOutcomes.join(', ')}   "
+                  "Configuration: '${testCase.configurationString}'");
+          }
+        });
+    }
+
+    void setupForRunning(TestCaseEnqueuer testCaseEnqueuer) {
+      bool recording = recordingOutputFile != null;
+      bool replaying = recordedInputFile != null;
+
+      // When the graph building is finished, notify event listeners.
+      _graph.events
+        .where((event) => event is dgraph.GraphSealedEvent).listen((event) {
+          eventAllTestsKnown();
+        });
+
+      // Queue commands as they become "runnable"
+      var commandEnqueuer = new CommandEnqueuer(_graph);
+
+      // CommandExecutor will execute commands
+      var executor;
+      if (recording) {
+        executor = new RecordingCommandExecutor(new Path(recordingOutputFile));
+      } else if (replaying) {
+        executor = new ReplayingCommandExecutor(new Path(recordedInputFile));
+      } else {
+        executor = new CommandExecutorImpl(
+            _globalConfiguration, maxProcesses, maxBrowserProcesses);
+      }
+
+      // Run "runnable commands" using [executor] subject to
+      // maxProcesses/maxBrowserProcesses constraint
+      var commandQueue = new CommandQueue(
+          _graph, testCaseEnqueuer, executor, maxProcesses, maxBrowserProcesses,
+          verbose);
+
+      // Finish test cases when all commands were run (or some failed)
+      var testCaseCompleter =
+          new TestCaseCompleter(_graph, testCaseEnqueuer, commandQueue);
+      testCaseCompleter.finishedTestCases.listen(
+          (TestCase finishedTestCase) {
+            // If we're recording, we don't report any TestCases to listeners.
+            if (!recording) {
+              eventFinishedTestCase(finishedTestCase);
+            }
+          },
+          onDone: () {
+            // Wait until the commandQueue/execturo is done (it may need to stop
+            // batch runners, browser controllers, ....)
+            commandQueue.done.then((_) => eventAllTestsDone());
+          });
+    }
 
     // Build up the dependency graph
     var testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) {
       eventTestAdded(newTestCase);
     });
 
-    // Queue commands as they become "runnable"
-    var commandEnqueuer = new CommandEnqueuer(_graph);
-
-    // CommandExecutor will execute commands
-    var executor;
-    if (recording) {
-      executor = new RecordingCommandExecutor(new Path(recordingOutputFile));
-    } else if (replaying) {
-      executor = new ReplayingCommandExecutor(new Path(recordedInputFile));
+    // Either list or run the tests
+    if (_globalConfiguration['list']) {
+      setupForListing(testCaseEnqueuer);
     } else {
-      executor = new CommandExecutorImpl(
-          _globalConfiguration, maxProcesses, maxBrowserProcesses);
+      setupForRunning(testCaseEnqueuer);
     }
 
-    // Run "runnable commands" using [executor] subject to
-    // maxProcesses/maxBrowserProcesses constraint
-    var commandQueue = new CommandQueue(
-        _graph, testCaseEnqueuer, executor, maxProcesses, maxBrowserProcesses,
-        verbose);
-
-    // Finish test cases when all commands were run (or some failed)
-    var testCaseCompleter =
-        new TestCaseCompleter(_graph, testCaseEnqueuer, commandQueue);
-    testCaseCompleter.finishedTestCases.listen(
-      (TestCase finishedTestCase) {
-        // If we're recording, we don't report any TestCases to listeners.
-        if (!recording) {
-          eventFinishedTestCase(finishedTestCase);
-        }
-      },
-      onDone: () {
-        // Wait until the commandQueue/execturo is done (it may need to stop
-        // batch runners, browser controllers, ....)
-        commandQueue.done.then((_) => eventAllTestsDone());
-      });
-
     // Start enqueing all TestCases
     testCaseEnqueuer.enqueueTestSuites(testSuites);
   }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 4ea2d16..c918b77 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -988,7 +988,7 @@
         // If necessary, run the Polymer deploy steps.
         // TODO(jmesserly): this should be generalized for any tests that
         // require Pub deploy, not just polymer.
-        if (customHtml.readAsStringSync().contains('polymer/boot.js')) {
+        if (customHtml.readAsStringSync().contains('polymer/init.dart')) {
           if (compiler != 'none') {
             commands.add(_polymerDeployCommand(
                 customHtmlPath, tempDir, optionsFromFile));
diff --git a/tools/utils.py b/tools/utils.py
index a81c7e6..8833930 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -462,6 +462,19 @@
   def __exit__(self, *_):
     shutil.rmtree(self._temp_dir, ignore_errors=True)
 
+class ChangedWorkingDirectory(object):
+  def __init__(self, working_directory):
+    self._working_directory = working_directory
+
+  def __enter__(self):
+    self._old_cwd = os.getcwd()
+    print "Enter directory = ", self._working_directory
+    os.chdir(self._working_directory)
+
+  def __exit__(self, *_):
+    print "Enter directory = ", self._old_cwd
+    os.chdir(self._old_cwd)
+
 
 if __name__ == "__main__":
   import sys
diff --git a/utils/apidoc/html_diff.dart b/utils/apidoc/html_diff.dart
index 1bb8069e..45ae9dd 100644
--- a/utils/apidoc/html_diff.dart
+++ b/utils/apidoc/html_diff.dart
@@ -90,7 +90,7 @@
    */
   Future run(Uri libraryRoot) {
     var result = new Completer();
-    var provider = new SourceFileProvider();
+    var provider = new CompilerSourceFileProvider();
     var handler = new FormattingDiagnosticHandler(provider);
     Future<MirrorSystem> analysis = analyze(
         HTML_LIBRARY_URIS, libraryRoot, null,