Version 0.8.0.0

svn merge -r 27984:28200 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@28224 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/bin/formatter.dart b/pkg/analyzer_experimental/bin/formatter.dart
index 02dc8f1..a8ea0fe 100755
--- a/pkg/analyzer_experimental/bin/formatter.dart
+++ b/pkg/analyzer_experimental/bin/formatter.dart
@@ -159,7 +159,11 @@
 _toJson(formatResult) => 
     // Actual JSON format TBD
     JSON.encode({'source': formatResult.source,
-                 'selection': formatResult.selection.toString()});
+                 'selection': {
+                     'offset': formatResult.selection.offset,
+                     'length': formatResult.selection.length
+                  }
+    });
 
 /// Log the given [msg].
 _log(String msg) {
diff --git a/pkg/analyzer_experimental/lib/options.dart b/pkg/analyzer_experimental/lib/options.dart
index efa3b5f..9b3ffac 100644
--- a/pkg/analyzer_experimental/lib/options.dart
+++ b/pkg/analyzer_experimental/lib/options.dart
@@ -26,6 +26,9 @@
   /** Whether to display version information */
   final bool displayVersion;
 
+  /** Whether to report hints */
+  final bool disableHints;
+
   /** Whether to ignore unrecognized flags */
   final bool ignoreUnrecognizedFlags;
 
@@ -57,6 +60,7 @@
     : shouldBatch = args['batch'],
       machineFormat = args['machine'],
       displayVersion = args['version'],
+      disableHints = args['no-hints'],
       ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
       perf = args['perf'],
       showPackageWarnings = args['show-package-warnings'],
@@ -102,6 +106,8 @@
           defaultsTo: false, negatable: false)
       ..addFlag('version', help: 'Print the analyzer version',
           defaultsTo: false, negatable: false)
+      ..addFlag('no-hints', help: 'Do not show hint results',
+          defaultsTo: false, negatable: false)
       ..addFlag('ignore-unrecognized-flags',
           help: 'Ignore unrecognized command line flags',
           defaultsTo: false, negatable: false)
diff --git a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
index 40b436c..2104617 100644
--- a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
@@ -86,6 +86,11 @@
     sourceFactory = new SourceFactory.con1(contentCache, resolvers);
     context = AnalysisEngine.instance.createAnalysisContext();
     context.sourceFactory = sourceFactory;
+
+    // set options for context
+    AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
+    contextOptions.hint = !options.disableHints;
+    context.analysisOptions = contextOptions;
   }
 
   /// Fills [sources].
@@ -139,6 +144,7 @@
   /// Fills [errorInfos].
   void prepareErrors() {
     for (Source source in sources) {
+      context.computeErrors(source);
       var sourceErrors = context.getErrors(source);
       errorInfos.add(sourceErrors);
     }
diff --git a/pkg/analyzer_experimental/lib/src/error_formatter.dart b/pkg/analyzer_experimental/lib/src/error_formatter.dart
index 47d718d..c26aaa4 100644
--- a/pkg/analyzer_experimental/lib/src/error_formatter.dart
+++ b/pkg/analyzer_experimental/lib/src/error_formatter.dart
@@ -46,41 +46,62 @@
     // format errors
     int errorCount = 0;
     int warnCount = 0;
+    int hintCount = 0;
     for (AnalysisError error in errors) {
-      if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) {
+      var severity = error.errorCode.errorSeverity;
+      if (severity == ErrorSeverity.ERROR) {
         errorCount++;
-      } else if (error.errorCode.errorSeverity == ErrorSeverity.WARNING) {
+      } else if (severity == ErrorSeverity.WARNING) {
         if (options.warningsAreFatal) {
           errorCount++;
         } else {
-          warnCount++;
+          if (error.errorCode.type == ErrorType.HINT) {
+            hintCount++;
+          } else {
+            warnCount++;
+          }
         }
       }
       formatError(errorToLine, error);
     }
     // print statistics
     if (!options.machineFormat) {
-      if (errorCount != 0 && warnCount != 0) {
+      var hasErrors = errorCount != 0;
+      var hasWarns = warnCount != 0;
+      var hasHints = hintCount != 0;
+      bool hasContent = false;
+      if (hasErrors) {
         out.write(errorCount);
         out.write(' ');
         out.write(pluralize("error", errorCount));
-        out.write(' and ');
+        hasContent = true;
+      }
+      if (hasWarns) {
+        if (hasContent) {
+          if (!hasHints) {
+            out.write(' and ');
+          } else {
+            out.write(", ");
+          }
+        }
         out.write(warnCount);
         out.write(' ');
         out.write(pluralize("warning", warnCount));
-        out.writeln(' found.');
-      } else if (errorCount != 0) {
-        out.write(errorCount);
+        hasContent = true;
+      }
+      if (hasHints) {
+        if (hasContent) {
+          out.write(" and ");
+        }
+        out.write(hintCount);
         out.write(' ');
-        out.write(pluralize("error", errorCount));
-        out.writeln(' found.');
-      } else if (warnCount != 0) {
-        out.write(warnCount);
-        out.write(' ');
-        out.write(pluralize("warning", warnCount));
-        out.writeln(' found.');
+        out.write(pluralize("hint", hintCount));
+        hasContent = true;
+      }
+      if (hasContent) {
+        out.writeln(" found.");
       } else {
-        out.writeln("No issues found.");
+        out.writeln("No issues found");
       }
     }
   }
@@ -110,8 +131,12 @@
       out.write('|');
       out.write(escapePipe(error.message));
     } else {
+      String errorType = error.errorCode.errorSeverity.displayName;
+      if (error.errorCode.type == ErrorType.HINT) {
+        errorType = error.errorCode.type.displayName;
+      }
       // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
-      out.write('[${severity.displayName}] ${error.message} ');
+      out.write('[$errorType] ${error.message} ');
       out.write('(${source.fullName}');
       out.write(', line ${location.lineNumber}, col ${location.columnNumber})');
     }
diff --git a/pkg/analyzer_experimental/lib/src/generated/ast.dart b/pkg/analyzer_experimental/lib/src/generated/ast.dart
index dea447d..3acc231 100644
--- a/pkg/analyzer_experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/ast.dart
@@ -116,7 +116,7 @@
     if (beginToken == null) {
       return -1;
     }
-    return beginToken.offset;
+    return this.beginToken.offset;
   }
 
   /**
@@ -484,8 +484,8 @@
    *
    * @param comment the documentation comment to be associated with this node
    */
-  void set documentationComment(Comment comment2) {
-    this._comment = becomeParentOf(comment2);
+  void set documentationComment(Comment comment) {
+    this._comment = becomeParentOf(comment);
   }
 
   /**
@@ -493,9 +493,9 @@
    *
    * @param metadata the metadata to be associated with this node
    */
-  void set metadata(List<Annotation> metadata2) {
+  void set metadata(List<Annotation> metadata) {
     this._metadata.clear();
-    this._metadata.addAll(metadata2);
+    this._metadata.addAll(metadata);
   }
   void visitChildren(ASTVisitor visitor) {
     if (commentIsBeforeAnnotations()) {
@@ -686,8 +686,8 @@
    *
    * @param arguments the arguments to the constructor being invoked
    */
-  void set arguments(ArgumentList arguments2) {
-    this._arguments = becomeParentOf(arguments2);
+  void set arguments(ArgumentList arguments) {
+    this._arguments = becomeParentOf(arguments);
   }
 
   /**
@@ -695,8 +695,8 @@
    *
    * @param constructorName the name of the constructor being invoked
    */
-  void set constructorName(SimpleIdentifier constructorName2) {
-    this._constructorName = becomeParentOf(constructorName2);
+  void set constructorName(SimpleIdentifier constructorName) {
+    this._constructorName = becomeParentOf(constructorName);
   }
 
   /**
@@ -704,8 +704,8 @@
    *
    * @param element the element to be associated with this identifier
    */
-  void set element(Element element2) {
-    this._element = element2;
+  void set element(Element element) {
+    this._element = element;
   }
 
   /**
@@ -714,8 +714,8 @@
    *
    * @param name the name of the constructor being invoked or the name of the field being referenced
    */
-  void set name(Identifier name2) {
-    this._name = becomeParentOf(name2);
+  void set name(Identifier name) {
+    this._name = becomeParentOf(name);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_name, visitor);
@@ -779,8 +779,8 @@
    *
    * @param identifier the identifier representing the argument being tested
    */
-  void set identifier(SimpleIdentifier identifier2) {
-    this._identifier = becomeParentOf(identifier2);
+  void set identifier(SimpleIdentifier identifier) {
+    this._identifier = becomeParentOf(identifier);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_identifier, visitor);
@@ -1046,8 +1046,8 @@
    *
    * @param expression the expression used to compute the value being cast
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
 
   /**
@@ -1143,8 +1143,8 @@
    *
    * @param the condition that is being asserted to be `true`
    */
-  void set condition(Expression condition2) {
-    this._condition = becomeParentOf(condition2);
+  void set condition(Expression condition) {
+    this._condition = becomeParentOf(condition);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_condition, visitor);
@@ -1655,8 +1655,8 @@
    *
    * @param block the block representing the body of the function
    */
-  void set block(Block block2) {
-    this._block = becomeParentOf(block2);
+  void set block(Block block) {
+    this._block = becomeParentOf(block);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_block, visitor);
@@ -1847,8 +1847,8 @@
    *
    * @param target the target of the cascade sections
    */
-  void set target(Expression target2) {
-    this._target = becomeParentOf(target2);
+  void set target(Expression target) {
+    this._target = becomeParentOf(target);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_target, visitor);
@@ -2214,8 +2214,8 @@
    *
    * @param extendsClause the extends clause for this class
    */
-  void set extendsClause(ExtendsClause extendsClause2) {
-    this._extendsClause = becomeParentOf(extendsClause2);
+  void set extendsClause(ExtendsClause extendsClause) {
+    this._extendsClause = becomeParentOf(extendsClause);
   }
 
   /**
@@ -2223,8 +2223,8 @@
    *
    * @param implementsClause the implements clause for the class
    */
-  void set implementsClause(ImplementsClause implementsClause2) {
-    this._implementsClause = becomeParentOf(implementsClause2);
+  void set implementsClause(ImplementsClause implementsClause) {
+    this._implementsClause = becomeParentOf(implementsClause);
   }
 
   /**
@@ -2241,8 +2241,8 @@
    *
    * @param withClause the with clause for the class
    */
-  void set withClause(WithClause withClause2) {
-    this._withClause = becomeParentOf(withClause2);
+  void set withClause(WithClause withClause) {
+    this._withClause = becomeParentOf(withClause);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -2422,8 +2422,8 @@
    *
    * @param implementsClause the implements clause for this class
    */
-  void set implementsClause(ImplementsClause implementsClause2) {
-    this._implementsClause = becomeParentOf(implementsClause2);
+  void set implementsClause(ImplementsClause implementsClause) {
+    this._implementsClause = becomeParentOf(implementsClause);
   }
 
   /**
@@ -2431,8 +2431,8 @@
    *
    * @param name the name of the class being declared
    */
-  void set name(SimpleIdentifier name2) {
-    this._name = becomeParentOf(name2);
+  void set name(SimpleIdentifier name) {
+    this._name = becomeParentOf(name);
   }
 
   /**
@@ -2440,8 +2440,8 @@
    *
    * @param superclass the name of the superclass of the class being declared
    */
-  void set superclass(TypeName superclass2) {
-    this._superclass = becomeParentOf(superclass2);
+  void set superclass(TypeName superclass) {
+    this._superclass = becomeParentOf(superclass);
   }
 
   /**
@@ -2449,8 +2449,8 @@
    *
    * @param typeParameters the type parameters for the class
    */
-  void set typeParameters(TypeParameterList typeParameters2) {
-    this._typeParameters = becomeParentOf(typeParameters2);
+  void set typeParameters(TypeParameterList typeParameters) {
+    this._typeParameters = becomeParentOf(typeParameters);
   }
 
   /**
@@ -2458,8 +2458,8 @@
    *
    * @param withClause the with clause for this class
    */
-  void set withClause(WithClause withClause2) {
-    this._withClause = becomeParentOf(withClause2);
+  void set withClause(WithClause withClause) {
+    this._withClause = becomeParentOf(withClause);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -2711,8 +2711,8 @@
    *
    * @param identifier the identifier being referenced
    */
-  void set identifier(Identifier identifier2) {
-    identifier2 = becomeParentOf(identifier2);
+  void set identifier(Identifier identifier) {
+    identifier = becomeParentOf(identifier);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_identifier, visitor);
@@ -2928,8 +2928,8 @@
    *
    * @param scriptTag the script tag at the beginning of the compilation unit
    */
-  void set scriptTag(ScriptTag scriptTag2) {
-    this._scriptTag = becomeParentOf(scriptTag2);
+  void set scriptTag(ScriptTag scriptTag) {
+    this._scriptTag = becomeParentOf(scriptTag);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_scriptTag, visitor);
@@ -3345,8 +3345,8 @@
    *
    * @param element the element associated with this constructor
    */
-  void set element(ConstructorElement element2) {
-    this._element = element2;
+  void set element(ConstructorElement element) {
+    this._element = element;
   }
 
   /**
@@ -3363,8 +3363,8 @@
    *
    * @param parameters the parameters associated with the constructor
    */
-  void set parameters(FormalParameterList parameters2) {
-    this._parameters = becomeParentOf(parameters2);
+  void set parameters(FormalParameterList parameters) {
+    this._parameters = becomeParentOf(parameters);
   }
 
   /**
@@ -3374,8 +3374,8 @@
    * @param redirectedConstructor the name of the constructor to which this constructor will be
    *          redirected
    */
-  void set redirectedConstructor(ConstructorName redirectedConstructor2) {
-    this._redirectedConstructor = becomeParentOf(redirectedConstructor2);
+  void set redirectedConstructor(ConstructorName redirectedConstructor) {
+    this._redirectedConstructor = becomeParentOf(redirectedConstructor);
   }
 
   /**
@@ -3396,9 +3396,9 @@
     safelyVisitChild(_body, visitor);
   }
   Token get firstTokenAfterCommentAndMetadata {
-    Token leftMost2 = leftMost([externalKeyword, constKeyword, factoryKeyword]);
-    if (leftMost2 != null) {
-      return leftMost2;
+    Token leftMost = this.leftMost([externalKeyword, constKeyword, factoryKeyword]);
+    if (leftMost != null) {
+      return leftMost;
     }
     return _returnType.beginToken;
   }
@@ -3518,8 +3518,8 @@
    *
    * @param expression the expression computing the value to which the field will be initialized
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
 
   /**
@@ -3644,8 +3644,8 @@
    *
    * @param name the name of the constructor
    */
-  void set name(SimpleIdentifier name2) {
-    this._name = becomeParentOf(name2);
+  void set name(SimpleIdentifier name) {
+    this._name = becomeParentOf(name);
   }
 
   /**
@@ -3663,8 +3663,8 @@
    *
    * @param type the name of the type defining the constructor
    */
-  void set type(TypeName type2) {
-    this._type = becomeParentOf(type2);
+  void set type(TypeName type) {
+    this._type = becomeParentOf(type);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_type, visitor);
@@ -3831,11 +3831,11 @@
   DeclaredIdentifier({Comment comment, List<Annotation> metadata, Token keyword, TypeName type, SimpleIdentifier identifier}) : this.full(comment, metadata, keyword, type, identifier);
   accept(ASTVisitor visitor) => visitor.visitDeclaredIdentifier(this);
   LocalVariableElement get element {
-    SimpleIdentifier identifier2 = identifier;
-    if (identifier2 == null) {
+    SimpleIdentifier identifier = this.identifier;
+    if (identifier == null) {
       return null;
     }
-    return identifier2.staticElement as LocalVariableElement;
+    return identifier.staticElement as LocalVariableElement;
   }
   Token get endToken => identifier.endToken;
 
@@ -3990,8 +3990,8 @@
    *
    * @param kind the kind of this parameter
    */
-  void set kind(ParameterKind kind2) {
-    this._kind = kind2;
+  void set kind(ParameterKind kind) {
+    this._kind = kind;
   }
 
   /**
@@ -4381,9 +4381,9 @@
   ExportDirective({Comment comment, List<Annotation> metadata, Token keyword, StringLiteral libraryUri, List<Combinator> combinators, Token semicolon}) : this.full(comment, metadata, keyword, libraryUri, combinators, semicolon);
   accept(ASTVisitor visitor) => visitor.visitExportDirective(this);
   LibraryElement get uriElement {
-    Element element2 = element;
-    if (element2 is ExportElement) {
-      return ((element2 as ExportElement)).exportedLibrary;
+    Element element = this.element;
+    if (element is ExportElement) {
+      return ((element as ExportElement)).exportedLibrary;
     }
     return null;
   }
@@ -4605,8 +4605,8 @@
    *
    * @param expression the expression representing the body of the function
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_expression, visitor);
@@ -4675,8 +4675,8 @@
    *
    * @param expression the expression that comprises the statement
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_expression, visitor);
@@ -4946,8 +4946,8 @@
    *
    * @param parameters the parameters of the function-typed parameter
    */
-  void set parameters(FormalParameterList parameters2) {
-    this._parameters = becomeParentOf(parameters2);
+  void set parameters(FormalParameterList parameters) {
+    this._parameters = becomeParentOf(parameters);
   }
 
   /**
@@ -5120,8 +5120,8 @@
    *
    * @param body the body of the loop
    */
-  void set body(Statement body2) {
-    this._body = becomeParentOf(body2);
+  void set body(Statement body) {
+    this._body = becomeParentOf(body);
   }
 
   /**
@@ -5129,8 +5129,8 @@
    *
    * @param identifier the loop variable
    */
-  void set identifier(SimpleIdentifier identifier2) {
-    this._identifier = becomeParentOf(identifier2);
+  void set identifier(SimpleIdentifier identifier) {
+    this._identifier = becomeParentOf(identifier);
   }
 
   /**
@@ -5312,8 +5312,8 @@
    *
    * @param body the body of the loop
    */
-  void set body(Statement body2) {
-    this._body = becomeParentOf(body2);
+  void set body(Statement body) {
+    this._body = becomeParentOf(body);
   }
 
   /**
@@ -5330,8 +5330,8 @@
    *
    * @param initialization the initialization expression
    */
-  void set initialization(Expression initialization2) {
-    this._initialization = becomeParentOf(initialization2);
+  void set initialization(Expression initialization) {
+    this._initialization = becomeParentOf(initialization);
   }
 
   /**
@@ -5722,8 +5722,8 @@
    *
    * @param functionExpression the function expression being wrapped
    */
-  void set functionExpression(FunctionExpression functionExpression2) {
-    functionExpression2 = becomeParentOf(functionExpression2);
+  void set functionExpression(FunctionExpression functionExpression) {
+    functionExpression = becomeParentOf(functionExpression);
   }
 
   /**
@@ -5800,8 +5800,8 @@
    *
    * @param functionDeclaration the function declaration being wrapped
    */
-  void set functionExpression(FunctionDeclaration functionDeclaration2) {
-    this.functionDeclaration = becomeParentOf(functionDeclaration2);
+  void set functionExpression(FunctionDeclaration functionDeclaration) {
+    this.functionDeclaration = becomeParentOf(functionDeclaration);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(functionDeclaration, visitor);
@@ -5899,8 +5899,8 @@
    *
    * @param parameters the parameters associated with the function
    */
-  void set parameters(FormalParameterList parameters2) {
-    this._parameters = becomeParentOf(parameters2);
+  void set parameters(FormalParameterList parameters) {
+    this._parameters = becomeParentOf(parameters);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_parameters, visitor);
@@ -6012,8 +6012,8 @@
    *
    * @param argumentList the list of arguments to the method
    */
-  void set argumentList(ArgumentList argumentList2) {
-    this._argumentList = becomeParentOf(argumentList2);
+  void set argumentList(ArgumentList argumentList) {
+    this._argumentList = becomeParentOf(argumentList);
   }
 
   /**
@@ -6021,8 +6021,8 @@
    *
    * @param function the expression producing the function being invoked
    */
-  void set function(Expression function2) {
-    function2 = becomeParentOf(function2);
+  void set function(Expression function) {
+    function = becomeParentOf(function);
   }
 
   /**
@@ -6146,8 +6146,8 @@
    *
    * @param name the name of the function type being declared
    */
-  void set name(SimpleIdentifier name2) {
-    this._name = becomeParentOf(name2);
+  void set name(SimpleIdentifier name) {
+    this._name = becomeParentOf(name);
   }
 
   /**
@@ -6155,8 +6155,8 @@
    *
    * @param parameters the parameters associated with the function type
    */
-  void set parameters(FormalParameterList parameters2) {
-    this._parameters = becomeParentOf(parameters2);
+  void set parameters(FormalParameterList parameters) {
+    this._parameters = becomeParentOf(parameters);
   }
 
   /**
@@ -6173,8 +6173,8 @@
    *
    * @param typeParameters the type parameters for the function type
    */
-  void set typeParameters(TypeParameterList typeParameters2) {
-    this._typeParameters = becomeParentOf(typeParameters2);
+  void set typeParameters(TypeParameterList typeParameters) {
+    this._typeParameters = becomeParentOf(typeParameters);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -6264,8 +6264,8 @@
    *
    * @param parameters the parameters of the function-typed parameter
    */
-  void set parameters(FormalParameterList parameters2) {
-    this._parameters = becomeParentOf(parameters2);
+  void set parameters(FormalParameterList parameters) {
+    this._parameters = becomeParentOf(parameters);
   }
 
   /**
@@ -6273,8 +6273,8 @@
    *
    * @param returnType the return type of the function
    */
-  void set returnType(TypeName returnType2) {
-    this._returnType = becomeParentOf(returnType2);
+  void set returnType(TypeName returnType) {
+    this._returnType = becomeParentOf(returnType);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -6724,9 +6724,9 @@
    */
   SimpleIdentifier get prefix => _prefix;
   LibraryElement get uriElement {
-    Element element2 = element;
-    if (element2 is ImportElement) {
-      return ((element2 as ImportElement)).importedLibrary;
+    Element element = this.element;
+    if (element is ImportElement) {
+      return ((element as ImportElement)).importedLibrary;
     }
     return null;
   }
@@ -6736,8 +6736,8 @@
    *
    * @param prefix the prefix to be used with the imported names
    */
-  void set prefix(SimpleIdentifier prefix2) {
-    this._prefix = becomeParentOf(prefix2);
+  void set prefix(SimpleIdentifier prefix) {
+    this._prefix = becomeParentOf(prefix);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -7184,8 +7184,8 @@
    *
    * @param argumentList the list of arguments to the constructor
    */
-  void set argumentList(ArgumentList argumentList2) {
-    this._argumentList = becomeParentOf(argumentList2);
+  void set argumentList(ArgumentList argumentList) {
+    this._argumentList = becomeParentOf(argumentList);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(constructorName, visitor);
@@ -7333,8 +7333,8 @@
    *
    * @param expression the expression to be evaluated for the value to be converted into a string
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_expression, visitor);
@@ -7499,8 +7499,8 @@
    *
    * @param expression the expression used to compute the value whose type is being tested
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
 
   /**
@@ -7572,8 +7572,8 @@
    *
    * @param label the label being associated with the statement
    */
-  void set label(SimpleIdentifier label2) {
-    this._label = becomeParentOf(label2);
+  void set label(SimpleIdentifier label) {
+    this._label = becomeParentOf(label);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_label, visitor);
@@ -7642,8 +7642,8 @@
    *
    * @param statement the statement with which the labels are being associated
    */
-  void set statement(Statement statement2) {
-    this._statement = becomeParentOf(statement2);
+  void set statement(Statement statement) {
+    this._statement = becomeParentOf(statement);
   }
   void visitChildren(ASTVisitor visitor) {
     labels.accept(visitor);
@@ -7718,8 +7718,8 @@
    *
    * @param name the name of the library being defined
    */
-  void set name(LibraryIdentifier name2) {
-    this._name = becomeParentOf(name2);
+  void set name(LibraryIdentifier name) {
+    this._name = becomeParentOf(name);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -7844,9 +7844,9 @@
     if (token != null) {
       return token;
     }
-    TypeArgumentList typeArguments2 = typeArguments;
-    if (typeArguments2 != null) {
-      return typeArguments2.beginToken;
+    TypeArgumentList typeArguments = this.typeArguments;
+    if (typeArguments != null) {
+      return typeArguments.beginToken;
     }
     return _leftBracket;
   }
@@ -7968,9 +7968,9 @@
     if (token != null) {
       return token;
     }
-    TypeArgumentList typeArguments2 = typeArguments;
-    if (typeArguments2 != null) {
-      return typeArguments2.beginToken;
+    TypeArgumentList typeArguments = this.typeArguments;
+    if (typeArguments != null) {
+      return typeArguments.beginToken;
     }
     return _leftBracket;
   }
@@ -8308,8 +8308,8 @@
    *
    * @param parameters the parameters associated with the method
    */
-  void set parameters(FormalParameterList parameters2) {
-    this._parameters = becomeParentOf(parameters2);
+  void set parameters(FormalParameterList parameters) {
+    this._parameters = becomeParentOf(parameters);
   }
 
   /**
@@ -8474,8 +8474,8 @@
    *
    * @param argumentList the list of arguments to the method
    */
-  void set argumentList(ArgumentList argumentList2) {
-    this._argumentList = becomeParentOf(argumentList2);
+  void set argumentList(ArgumentList argumentList) {
+    this._argumentList = becomeParentOf(argumentList);
   }
 
   /**
@@ -8580,8 +8580,8 @@
    *
    * @param expression the expression with which the name is associated
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
 
   /**
@@ -8849,8 +8849,8 @@
    *
    * @param comment the documentation comment to be associated with this parameter
    */
-  void set documentationComment(Comment comment2) {
-    this._comment = becomeParentOf(comment2);
+  void set documentationComment(Comment comment) {
+    this._comment = becomeParentOf(comment);
   }
 
   /**
@@ -8858,8 +8858,8 @@
    *
    * @param identifier the name of the parameter being declared
    */
-  void set identifier(SimpleIdentifier identifier2) {
-    this._identifier = becomeParentOf(identifier2);
+  void set identifier(SimpleIdentifier identifier) {
+    this._identifier = becomeParentOf(identifier);
   }
   void visitChildren(ASTVisitor visitor) {
     if (commentIsBeforeAnnotations()) {
@@ -9017,8 +9017,8 @@
    *
    * @param expression the expression within the parentheses
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
 
   /**
@@ -9170,8 +9170,8 @@
    *
    * @param libraryName the name of the library that the containing compilation unit is part of
    */
-  void set libraryName(LibraryIdentifier libraryName2) {
-    this._libraryName = becomeParentOf(libraryName2);
+  void set libraryName(LibraryIdentifier libraryName) {
+    this._libraryName = becomeParentOf(libraryName);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -9621,8 +9621,8 @@
    *
    * @param identifier the identifier being prefixed
    */
-  void set identifier(SimpleIdentifier identifier2) {
-    this._identifier = becomeParentOf(identifier2);
+  void set identifier(SimpleIdentifier identifier) {
+    this._identifier = becomeParentOf(identifier);
   }
 
   /**
@@ -9863,8 +9863,8 @@
    *
    * @param argumentList the list of arguments to the constructor
    */
-  void set argumentList(ArgumentList argumentList2) {
-    this._argumentList = becomeParentOf(argumentList2);
+  void set argumentList(ArgumentList argumentList) {
+    this._argumentList = becomeParentOf(argumentList);
   }
 
   /**
@@ -9984,8 +9984,8 @@
    *
    * @param expression the expression computing the value to be returned
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_expression, visitor);
@@ -10710,8 +10710,8 @@
    *
    * @param argumentList the list of arguments to the constructor
    */
-  void set argumentList(ArgumentList argumentList2) {
-    this._argumentList = becomeParentOf(argumentList2);
+  void set argumentList(ArgumentList argumentList) {
+    this._argumentList = becomeParentOf(argumentList);
   }
 
   /**
@@ -10819,8 +10819,8 @@
    *
    * @param expression the expression controlling whether the statements will be executed
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
   void visitChildren(ASTVisitor visitor) {
     labels.accept(visitor);
@@ -11036,8 +11036,8 @@
    *
    * @param expression the expression used to determine which of the switch members will be selected
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_expression, visitor);
@@ -11189,8 +11189,8 @@
    *
    * @param expression the expression computing the exception to be thrown
    */
-  void set expression(Expression expression2) {
-    this._expression = becomeParentOf(expression2);
+  void set expression(Expression expression) {
+    this._expression = becomeParentOf(expression);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_expression, visitor);
@@ -11582,8 +11582,8 @@
    *
    * @param typeArguments the type arguments associated with the type
    */
-  void set typeArguments(TypeArgumentList typeArguments2) {
-    this._typeArguments = becomeParentOf(typeArguments2);
+  void set typeArguments(TypeArgumentList typeArguments) {
+    this._typeArguments = becomeParentOf(typeArguments);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_name, visitor);
@@ -11858,8 +11858,8 @@
    *
    * @param uri the URI referenced by this directive
    */
-  void set uri(StringLiteral uri2) {
-    this._uri = becomeParentOf(uri2);
+  void set uri(StringLiteral uri) {
+    this._uri = becomeParentOf(uri);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -11990,8 +11990,8 @@
    *
    * @param initializer the expression used to compute the initial value for the variable
    */
-  void set initializer(Expression initializer2) {
-    this._initializer = becomeParentOf(initializer2);
+  void set initializer(Expression initializer) {
+    this._initializer = becomeParentOf(initializer);
   }
 
   /**
@@ -11999,8 +11999,8 @@
    *
    * @param name the name of the variable being declared
    */
-  void set name(SimpleIdentifier name2) {
-    this._name = becomeParentOf(name2);
+  void set name(SimpleIdentifier name) {
+    this._name = becomeParentOf(name);
   }
   void visitChildren(ASTVisitor visitor) {
     super.visitChildren(visitor);
@@ -12174,8 +12174,8 @@
    *
    * @param variableList the variables being declared
    */
-  void set variables(VariableDeclarationList variableList2) {
-    this._variableList = becomeParentOf(variableList2);
+  void set variables(VariableDeclarationList variableList) {
+    this._variableList = becomeParentOf(variableList);
   }
   void visitChildren(ASTVisitor visitor) {
     safelyVisitChild(_variableList, visitor);
@@ -12336,8 +12336,8 @@
    *
    * @param withKeyword the token representing the 'with' keyword
    */
-  void set mixinKeyword(Token withKeyword2) {
-    this.withKeyword = withKeyword2;
+  void set mixinKeyword(Token withKeyword) {
+    this.withKeyword = withKeyword;
   }
   void visitChildren(ASTVisitor visitor) {
     mixinTypes.accept(visitor);
diff --git a/pkg/analyzer_experimental/lib/src/generated/constant.dart b/pkg/analyzer_experimental/lib/src/generated/constant.dart
index ac6bf34..2403231 100644
--- a/pkg/analyzer_experimental/lib/src/generated/constant.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/constant.dart
@@ -1103,16 +1103,16 @@
     return value.toString();
   }
   EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
-    } else if (isSomeNum || leftOperand2.isSomeNum) {
+    } else if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_NUM;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1137,14 +1137,14 @@
     return error(node);
   }
   EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyInt || !leftOperand2.isAnyInt) {
+  EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyInt || !leftOperand.isAnyInt) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1161,14 +1161,14 @@
     return union(error(node.leftOperand), error(node.rightOperand));
   }
   EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyInt || !leftOperand2.isAnyInt) {
+  EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyInt || !leftOperand.isAnyInt) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1185,14 +1185,14 @@
     return union(error(node.leftOperand), error(node.rightOperand));
   }
   EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyInt || !leftOperand2.isAnyInt) {
+  EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyInt || !leftOperand.isAnyInt) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1217,14 +1217,14 @@
     return error(node);
   }
   EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeNum || leftOperand2.isSomeNum) {
+    if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_NUM;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1286,14 +1286,14 @@
   }
   EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
   EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeNum || leftOperand2.isSomeNum) {
+    if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_BOOL;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1313,14 +1313,14 @@
     }
     return error(node);
   }
-  EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeNum || leftOperand2.isSomeNum) {
+    if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_BOOL;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1341,14 +1341,14 @@
     return error(node);
   }
   EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeNum || leftOperand2.isSomeNum) {
+    if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_INT;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1376,14 +1376,14 @@
   }
   EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
   EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeNum || leftOperand2.isSomeNum) {
+    if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_BOOL;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1403,14 +1403,14 @@
     }
     return error(node);
   }
-  EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeNum || leftOperand2.isSomeNum) {
+    if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_BOOL;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1462,16 +1462,16 @@
     return booleanConversion(node.rightOperand, value);
   }
   EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
-    } else if (isSomeNum || leftOperand2.isSomeNum) {
+    } else if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_NUM;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1527,16 +1527,16 @@
     return RESULT_TRUE;
   }
   EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
-    } else if (isSomeNum || leftOperand2.isSomeNum) {
+    } else if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_NUM;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1560,14 +1560,14 @@
     return error(node);
   }
   EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyInt || !leftOperand2.isAnyInt) {
+  EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyInt || !leftOperand.isAnyInt) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1584,14 +1584,14 @@
     return union(error(node.leftOperand), error(node.rightOperand));
   }
   EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyInt || !leftOperand2.isAnyInt) {
+  EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyInt || !leftOperand.isAnyInt) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
@@ -1608,16 +1608,16 @@
     return union(error(node.leftOperand), error(node.rightOperand));
   }
   EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-  EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand2) {
-    if (!isAnyNum || !leftOperand2.isAnyNum) {
+  EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand) {
+    if (!isAnyNum || !leftOperand.isAnyNum) {
       return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
     }
-    if (isSomeInt || leftOperand2.isSomeInt) {
+    if (isSomeInt || leftOperand.isSomeInt) {
       return RESULT_INT;
-    } else if (isSomeNum || leftOperand2.isSomeNum) {
+    } else if (isSomeNum || leftOperand.isSomeNum) {
       return RESULT_NUM;
     }
-    Object leftValue = leftOperand2.value;
+    Object leftValue = leftOperand.value;
     if (leftValue == null) {
       return error(node.leftOperand);
     } else if (value == null) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/element.dart b/pkg/analyzer_experimental/lib/src/generated/element.dart
index fa3c4be..776fbf2 100644
--- a/pkg/analyzer_experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/element.dart
@@ -1812,29 +1812,29 @@
     collectAllSupertypes(list);
     return new List.from(list);
   }
-  ElementImpl getChild(String identifier2) {
+  ElementImpl getChild(String identifier) {
     for (PropertyAccessorElement accessor in _accessors) {
-      if (((accessor as PropertyAccessorElementImpl)).identifier == identifier2) {
+      if (((accessor as PropertyAccessorElementImpl)).identifier == identifier) {
         return accessor as PropertyAccessorElementImpl;
       }
     }
     for (ConstructorElement constructor in _constructors) {
-      if (((constructor as ConstructorElementImpl)).identifier == identifier2) {
+      if (((constructor as ConstructorElementImpl)).identifier == identifier) {
         return constructor as ConstructorElementImpl;
       }
     }
     for (FieldElement field in _fields) {
-      if (((field as FieldElementImpl)).identifier == identifier2) {
+      if (((field as FieldElementImpl)).identifier == identifier) {
         return field as FieldElementImpl;
       }
     }
     for (MethodElement method in _methods) {
-      if (((method as MethodElementImpl)).identifier == identifier2) {
+      if (((method as MethodElementImpl)).identifier == identifier) {
         return method as MethodElementImpl;
       }
     }
     for (TypeParameterElement typeParameter in _typeParameters) {
-      if (((typeParameter as TypeParameterElementImpl)).identifier == identifier2) {
+      if (((typeParameter as TypeParameterElementImpl)).identifier == identifier) {
         return typeParameter as TypeParameterElementImpl;
       }
     }
@@ -1849,9 +1849,9 @@
    * @param name some name to lookup a field element with
    * @return the matching field element, or `null` if no such element was found
    */
-  FieldElement getField(String name2) {
+  FieldElement getField(String name) {
     for (FieldElement fieldElement in _fields) {
-      if (name2 == fieldElement.name) {
+      if (name == fieldElement.name) {
         return fieldElement;
       }
     }
@@ -1878,10 +1878,10 @@
   }
   List<MethodElement> get methods => _methods;
   List<InterfaceType> get mixins => _mixins;
-  ConstructorElement getNamedConstructor(String name2) {
+  ConstructorElement getNamedConstructor(String name) {
     for (ConstructorElement element in constructors) {
       String elementName = element.name;
-      if (elementName != null && elementName == name2) {
+      if (elementName != null && elementName == name) {
         return element;
       }
     }
@@ -2034,11 +2034,11 @@
    *
    * @param accessors the accessors contained in this class
    */
-  void set accessors(List<PropertyAccessorElement> accessors2) {
-    for (PropertyAccessorElement accessor in accessors2) {
+  void set accessors(List<PropertyAccessorElement> accessors) {
+    for (PropertyAccessorElement accessor in accessors) {
       ((accessor as PropertyAccessorElementImpl)).enclosingElement = this;
     }
-    this._accessors = accessors2;
+    this._accessors = accessors;
   }
 
   /**
@@ -2046,11 +2046,11 @@
    *
    * @param constructors the constructors contained in this class
    */
-  void set constructors(List<ConstructorElement> constructors2) {
-    for (ConstructorElement constructor in constructors2) {
+  void set constructors(List<ConstructorElement> constructors) {
+    for (ConstructorElement constructor in constructors) {
       ((constructor as ConstructorElementImpl)).enclosingElement = this;
     }
-    this._constructors = constructors2;
+    this._constructors = constructors;
   }
 
   /**
@@ -2058,11 +2058,11 @@
    *
    * @param fields the fields contained in this class
    */
-  void set fields(List<FieldElement> fields2) {
-    for (FieldElement field in fields2) {
+  void set fields(List<FieldElement> fields) {
+    for (FieldElement field in fields) {
       ((field as FieldElementImpl)).enclosingElement = this;
     }
-    this._fields = fields2;
+    this._fields = fields;
   }
 
   /**
@@ -2079,8 +2079,8 @@
    *
    * @param the interfaces that are implemented by this class
    */
-  void set interfaces(List<InterfaceType> interfaces2) {
-    this._interfaces = interfaces2;
+  void set interfaces(List<InterfaceType> interfaces) {
+    this._interfaces = interfaces;
   }
 
   /**
@@ -2088,11 +2088,11 @@
    *
    * @param methods the methods contained in this class
    */
-  void set methods(List<MethodElement> methods2) {
-    for (MethodElement method in methods2) {
+  void set methods(List<MethodElement> methods) {
+    for (MethodElement method in methods) {
       ((method as MethodElementImpl)).enclosingElement = this;
     }
-    this._methods = methods2;
+    this._methods = methods;
   }
 
   /**
@@ -2101,8 +2101,8 @@
    *
    * @param mixins the mixins that are applied to derive the superclass of this class
    */
-  void set mixins(List<InterfaceType> mixins2) {
-    this._mixins = mixins2;
+  void set mixins(List<InterfaceType> mixins) {
+    this._mixins = mixins;
   }
 
   /**
@@ -2110,8 +2110,8 @@
    *
    * @param supertype the superclass of the class
    */
-  void set supertype(InterfaceType supertype2) {
-    this._supertype = supertype2;
+  void set supertype(InterfaceType supertype) {
+    this._supertype = supertype;
   }
 
   /**
@@ -2119,8 +2119,8 @@
    *
    * @param type the type defined by the class
    */
-  void set type(InterfaceType type2) {
-    this._type = type2;
+  void set type(InterfaceType type) {
+    this._type = type;
   }
 
   /**
@@ -2137,11 +2137,11 @@
    *
    * @param typeParameters the type parameters defined for this class
    */
-  void set typeParameters(List<TypeParameterElement> typeParameters2) {
-    for (TypeParameterElement typeParameter in typeParameters2) {
+  void set typeParameters(List<TypeParameterElement> typeParameters) {
+    for (TypeParameterElement typeParameter in typeParameters) {
       ((typeParameter as TypeParameterElementImpl)).enclosingElement = this;
     }
-    this._typeParameters = typeParameters2;
+    this._typeParameters = typeParameters;
   }
 
   /**
@@ -2267,29 +2267,29 @@
   accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this);
   bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && _source == ((object as CompilationUnitElementImpl)).source;
   List<PropertyAccessorElement> get accessors => _accessors;
-  ElementImpl getChild(String identifier2) {
+  ElementImpl getChild(String identifier) {
     for (PropertyAccessorElement accessor in _accessors) {
-      if (((accessor as PropertyAccessorElementImpl)).identifier == identifier2) {
+      if (((accessor as PropertyAccessorElementImpl)).identifier == identifier) {
         return accessor as PropertyAccessorElementImpl;
       }
     }
     for (VariableElement variable in _variables) {
-      if (((variable as VariableElementImpl)).identifier == identifier2) {
+      if (((variable as VariableElementImpl)).identifier == identifier) {
         return variable as VariableElementImpl;
       }
     }
     for (ExecutableElement function in _functions) {
-      if (((function as ExecutableElementImpl)).identifier == identifier2) {
+      if (((function as ExecutableElementImpl)).identifier == identifier) {
         return function as ExecutableElementImpl;
       }
     }
     for (FunctionTypeAliasElement typeAlias in _typeAliases) {
-      if (((typeAlias as FunctionTypeAliasElementImpl)).identifier == identifier2) {
+      if (((typeAlias as FunctionTypeAliasElementImpl)).identifier == identifier) {
         return typeAlias as FunctionTypeAliasElementImpl;
       }
     }
     for (ClassElement type in _types) {
-      if (((type as ClassElementImpl)).identifier == identifier2) {
+      if (((type as ClassElementImpl)).identifier == identifier) {
         return type as ClassElementImpl;
       }
     }
@@ -2320,11 +2320,11 @@
    *
    * @param the top-level accessors (getters and setters) contained in this compilation unit
    */
-  void set accessors(List<PropertyAccessorElement> accessors2) {
-    for (PropertyAccessorElement accessor in accessors2) {
+  void set accessors(List<PropertyAccessorElement> accessors) {
+    for (PropertyAccessorElement accessor in accessors) {
       ((accessor as PropertyAccessorElementImpl)).enclosingElement = this;
     }
-    this._accessors = accessors2;
+    this._accessors = accessors;
   }
 
   /**
@@ -2332,11 +2332,11 @@
    *
    * @param functions the top-level functions contained in this compilation unit
    */
-  void set functions(List<FunctionElement> functions2) {
-    for (FunctionElement function in functions2) {
+  void set functions(List<FunctionElement> functions) {
+    for (FunctionElement function in functions) {
       ((function as FunctionElementImpl)).enclosingElement = this;
     }
-    this._functions = functions2;
+    this._functions = functions;
   }
 
   /**
@@ -2344,8 +2344,8 @@
    *
    * @param source the source that corresponds to this compilation unit
    */
-  void set source(Source source2) {
-    this._source = source2;
+  void set source(Source source) {
+    this._source = source;
   }
 
   /**
@@ -2353,11 +2353,11 @@
    *
    * @param variables the top-level variables contained in this compilation unit
    */
-  void set topLevelVariables(List<TopLevelVariableElement> variables2) {
-    for (TopLevelVariableElement field in variables2) {
+  void set topLevelVariables(List<TopLevelVariableElement> variables) {
+    for (TopLevelVariableElement field in variables) {
       ((field as TopLevelVariableElementImpl)).enclosingElement = this;
     }
-    this._variables = variables2;
+    this._variables = variables;
   }
 
   /**
@@ -2365,11 +2365,11 @@
    *
    * @param typeAliases the function type aliases contained in this compilation unit
    */
-  void set typeAliases(List<FunctionTypeAliasElement> typeAliases2) {
-    for (FunctionTypeAliasElement typeAlias in typeAliases2) {
+  void set typeAliases(List<FunctionTypeAliasElement> typeAliases) {
+    for (FunctionTypeAliasElement typeAlias in typeAliases) {
       ((typeAlias as FunctionTypeAliasElementImpl)).enclosingElement = this;
     }
-    this._typeAliases = typeAliases2;
+    this._typeAliases = typeAliases;
   }
 
   /**
@@ -2377,11 +2377,11 @@
    *
    * @param types types contained in this compilation unit
    */
-  void set types(List<ClassElement> types2) {
-    for (ClassElement type in types2) {
+  void set types(List<ClassElement> types) {
+    for (ClassElement type in types) {
       ((type as ClassElementImpl)).enclosingElement = this;
     }
-    this._types = types2;
+    this._types = types;
   }
 
   /**
@@ -2389,8 +2389,8 @@
    *
    * @param uri the URI that is specified by the "part" directive in the enclosing library.
    */
-  void set uri(String uri2) {
-    this._uri = uri2;
+  void set uri(String uri) {
+    this._uri = uri;
   }
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -2426,8 +2426,8 @@
    */
   ConstFieldElementImpl(Identifier name) : super.con1(name);
   EvaluationResultImpl get evaluationResult => _result;
-  void set evaluationResult(EvaluationResultImpl result2) {
-    this._result = result2;
+  void set evaluationResult(EvaluationResultImpl result) {
+    this._result = result;
   }
 }
 /**
@@ -2450,8 +2450,8 @@
    */
   ConstLocalVariableElementImpl(Identifier name) : super(name);
   EvaluationResultImpl get evaluationResult => _result;
-  void set evaluationResult(EvaluationResultImpl result2) {
-    this._result = result2;
+  void set evaluationResult(EvaluationResultImpl result) {
+    this._result = result;
   }
 }
 /**
@@ -2472,8 +2472,8 @@
    */
   ConstTopLevelVariableElementImpl(Identifier name) : super.con1(name);
   EvaluationResultImpl get evaluationResult => _result;
-  void set evaluationResult(EvaluationResultImpl result2) {
-    this._result = result2;
+  void set evaluationResult(EvaluationResultImpl result) {
+    this._result = result;
   }
 }
 /**
@@ -2542,8 +2542,8 @@
    *
    * @param redirectedConstructor the constructor to which this constructor is redirecting
    */
-  void set redirectedConstructor(ConstructorElement redirectedConstructor2) {
-    this._redirectedConstructor = redirectedConstructor2;
+  void set redirectedConstructor(ConstructorElement redirectedConstructor) {
+    this._redirectedConstructor = redirectedConstructor;
   }
   void appendTo(JavaStringBuilder builder) {
     builder.append(enclosingElement.displayName);
@@ -2575,8 +2575,8 @@
    */
   DefaultFieldFormalParameterElementImpl(Identifier name) : super(name);
   EvaluationResultImpl get evaluationResult => _result;
-  void set evaluationResult(EvaluationResultImpl result2) {
-    this._result = result2;
+  void set evaluationResult(EvaluationResultImpl result) {
+    this._result = result;
   }
 }
 /**
@@ -2599,8 +2599,8 @@
    */
   DefaultParameterElementImpl(Identifier name) : super.con1(name);
   EvaluationResultImpl get evaluationResult => _result;
-  void set evaluationResult(EvaluationResultImpl result2) {
-    this._result = result2;
+  void set evaluationResult(EvaluationResultImpl result) {
+    this._result = result;
   }
 }
 /**
@@ -2770,9 +2770,9 @@
     }
     return _cachedHashCode;
   }
-  bool isAccessibleIn(LibraryElement library2) {
+  bool isAccessibleIn(LibraryElement library) {
     if (Identifier.isPrivateName(_name)) {
-      return library2 == library;
+      return library == this.library;
     }
     return true;
   }
@@ -2783,8 +2783,8 @@
    *
    * @param metadata the metadata to be associated with this element
    */
-  void set metadata(List<ElementAnnotation> metadata2) {
-    this._metadata = metadata2;
+  void set metadata(List<ElementAnnotation> metadata) {
+    this._metadata = metadata;
   }
 
   /**
@@ -2794,8 +2794,8 @@
    *
    * @param nameOffset the offset to the beginning of the name
    */
-  void set nameOffset(int nameOffset2) {
-    this._nameOffset = nameOffset2;
+  void set nameOffset(int nameOffset) {
+    this._nameOffset = nameOffset;
   }
 
   /**
@@ -3092,9 +3092,9 @@
    *
    * @param scriptLibrary the library or `null` if none
    */
-  void set scriptLibrary(LibraryElementImpl scriptLibrary2) {
-    scriptLibrary2.enclosingElement = this;
-    this._scriptLibrary = scriptLibrary2;
+  void set scriptLibrary(LibraryElementImpl scriptLibrary) {
+    scriptLibrary.enclosingElement = this;
+    this._scriptLibrary = scriptLibrary;
   }
   void visitChildren(ElementVisitor visitor) {
     safelyVisitChild(_scriptLibrary, visitor);
@@ -3158,24 +3158,24 @@
    *          declaration of this element
    */
   ExecutableElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset);
-  ElementImpl getChild(String identifier2) {
+  ElementImpl getChild(String identifier) {
     for (ExecutableElement function in _functions) {
-      if (((function as ExecutableElementImpl)).identifier == identifier2) {
+      if (((function as ExecutableElementImpl)).identifier == identifier) {
         return function as ExecutableElementImpl;
       }
     }
     for (LabelElement label in _labels) {
-      if (((label as LabelElementImpl)).identifier == identifier2) {
+      if (((label as LabelElementImpl)).identifier == identifier) {
         return label as LabelElementImpl;
       }
     }
     for (VariableElement variable in _localVariables) {
-      if (((variable as VariableElementImpl)).identifier == identifier2) {
+      if (((variable as VariableElementImpl)).identifier == identifier) {
         return variable as VariableElementImpl;
       }
     }
     for (ParameterElement parameter in _parameters) {
-      if (((parameter as ParameterElementImpl)).identifier == identifier2) {
+      if (((parameter as ParameterElementImpl)).identifier == identifier) {
         return parameter as ParameterElementImpl;
       }
     }
@@ -3194,11 +3194,11 @@
    *
    * @param functions the functions defined within this executable element
    */
-  void set functions(List<FunctionElement> functions2) {
-    for (FunctionElement function in functions2) {
+  void set functions(List<FunctionElement> functions) {
+    for (FunctionElement function in functions) {
       ((function as FunctionElementImpl)).enclosingElement = this;
     }
-    this._functions = functions2;
+    this._functions = functions;
   }
 
   /**
@@ -3206,11 +3206,11 @@
    *
    * @param labels the labels defined within this executable element
    */
-  void set labels(List<LabelElement> labels2) {
-    for (LabelElement label in labels2) {
+  void set labels(List<LabelElement> labels) {
+    for (LabelElement label in labels) {
       ((label as LabelElementImpl)).enclosingElement = this;
     }
-    this._labels = labels2;
+    this._labels = labels;
   }
 
   /**
@@ -3218,11 +3218,11 @@
    *
    * @param localVariables the local variables defined within this executable element
    */
-  void set localVariables(List<LocalVariableElement> localVariables2) {
-    for (LocalVariableElement variable in localVariables2) {
+  void set localVariables(List<LocalVariableElement> localVariables) {
+    for (LocalVariableElement variable in localVariables) {
       ((variable as LocalVariableElementImpl)).enclosingElement = this;
     }
-    this._localVariables = localVariables2;
+    this._localVariables = localVariables;
   }
 
   /**
@@ -3230,11 +3230,11 @@
    *
    * @param parameters the parameters defined by this executable element
    */
-  void set parameters(List<ParameterElement> parameters2) {
-    for (ParameterElement parameter in parameters2) {
+  void set parameters(List<ParameterElement> parameters) {
+    for (ParameterElement parameter in parameters) {
       ((parameter as ParameterElementImpl)).enclosingElement = this;
     }
-    this._parameters = parameters2;
+    this._parameters = parameters;
   }
 
   /**
@@ -3242,8 +3242,8 @@
    *
    * @param returnType the return type defined by this executable element
    */
-  void set returnType(Type2 returnType2) {
-    this._returnType = returnType2;
+  void set returnType(Type2 returnType) {
+    this._returnType = returnType;
   }
 
   /**
@@ -3251,8 +3251,8 @@
    *
    * @param type the type of function defined by this executable element
    */
-  void set type(FunctionType type2) {
-    this._type = type2;
+  void set type(FunctionType type) {
+    this._type = type;
   }
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -3316,8 +3316,8 @@
    *
    * @param combinators the combinators that were specified as part of the export directive
    */
-  void set combinators(List<NamespaceCombinator> combinators2) {
-    this._combinators = combinators2;
+  void set combinators(List<NamespaceCombinator> combinators) {
+    this._combinators = combinators;
   }
 
   /**
@@ -3326,8 +3326,8 @@
    *
    * @param exportedLibrary the library that is exported from this library
    */
-  void set exportedLibrary(LibraryElement exportedLibrary2) {
-    this._exportedLibrary = exportedLibrary2;
+  void set exportedLibrary(LibraryElement exportedLibrary) {
+    this._exportedLibrary = exportedLibrary;
   }
 
   /**
@@ -3335,8 +3335,8 @@
    *
    * @param uri the URI that is specified by this directive.
    */
-  void set uri(String uri2) {
-    this._uri = uri2;
+  void set uri(String uri) {
+    this._uri = uri;
   }
   void appendTo(JavaStringBuilder builder) {
     builder.append("export ");
@@ -3372,8 +3372,8 @@
    *
    * @param scriptSource the script source or `null` if unspecified
    */
-  void set scriptSource(Source scriptSource2) {
-    this._scriptSource = scriptSource2;
+  void set scriptSource(Source scriptSource) {
+    this._scriptSource = scriptSource;
   }
 }
 /**
@@ -3444,8 +3444,8 @@
    *
    * @param field the new field element
    */
-  void set field(FieldElement field2) {
-    this._field = field2;
+  void set field(FieldElement field) {
+    this._field = field;
   }
 }
 /**
@@ -3564,14 +3564,14 @@
    */
   FunctionTypeAliasElementImpl(Identifier name) : super.con1(name);
   accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this);
-  ElementImpl getChild(String identifier2) {
+  ElementImpl getChild(String identifier) {
     for (VariableElement parameter in _parameters) {
-      if (((parameter as VariableElementImpl)).identifier == identifier2) {
+      if (((parameter as VariableElementImpl)).identifier == identifier) {
         return parameter as VariableElementImpl;
       }
     }
     for (TypeParameterElement typeParameter in _typeParameters) {
-      if (((typeParameter as TypeParameterElementImpl)).identifier == identifier2) {
+      if (((typeParameter as TypeParameterElementImpl)).identifier == identifier) {
         return typeParameter as TypeParameterElementImpl;
       }
     }
@@ -3589,13 +3589,13 @@
    *
    * @param parameters the parameters defined by this type alias
    */
-  void set parameters(List<ParameterElement> parameters2) {
-    if (parameters2 != null) {
-      for (ParameterElement parameter in parameters2) {
+  void set parameters(List<ParameterElement> parameters) {
+    if (parameters != null) {
+      for (ParameterElement parameter in parameters) {
         ((parameter as ParameterElementImpl)).enclosingElement = this;
       }
     }
-    this._parameters = parameters2;
+    this._parameters = parameters;
   }
 
   /**
@@ -3603,8 +3603,8 @@
    *
    * @param returnType the return type defined by this type alias
    */
-  void set returnType(Type2 returnType2) {
-    this._returnType = returnType2;
+  void set returnType(Type2 returnType) {
+    this._returnType = returnType;
   }
 
   /**
@@ -3612,8 +3612,8 @@
    *
    * @param type the type of function defined by this type alias
    */
-  void set type(FunctionType type2) {
-    this._type = type2;
+  void set type(FunctionType type) {
+    this._type = type;
   }
 
   /**
@@ -3621,11 +3621,11 @@
    *
    * @param typeParameters the type parameters defined for this type
    */
-  void set typeParameters(List<TypeParameterElement> typeParameters2) {
-    for (TypeParameterElement typeParameter in typeParameters2) {
+  void set typeParameters(List<TypeParameterElement> typeParameters) {
+    for (TypeParameterElement typeParameter in typeParameters) {
       ((typeParameter as TypeParameterElementImpl)).enclosingElement = this;
     }
-    this._typeParameters = typeParameters2;
+    this._typeParameters = typeParameters;
   }
 
   /**
@@ -3635,8 +3635,8 @@
    *
    * @param parameters the parameters defined by this type alias
    */
-  void shareParameters(List<ParameterElement> parameters2) {
-    this._parameters = parameters2;
+  void shareParameters(List<ParameterElement> parameters) {
+    this._parameters = parameters;
   }
 
   /**
@@ -3646,8 +3646,8 @@
    *
    * @param typeParameters the type parameters defined for this type
    */
-  void shareTypeParameters(List<TypeParameterElement> typeParameters2) {
-    this._typeParameters = typeParameters2;
+  void shareTypeParameters(List<TypeParameterElement> typeParameters) {
+    this._typeParameters = typeParameters;
   }
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -3704,8 +3704,8 @@
    *
    * @param hiddenNames the names that are not to be made visible in the importing library
    */
-  void set hiddenNames(List<String> hiddenNames2) {
-    this._hiddenNames = hiddenNames2;
+  void set hiddenNames(List<String> hiddenNames) {
+    this._hiddenNames = hiddenNames;
   }
   String toString() {
     JavaStringBuilder builder = new JavaStringBuilder();
@@ -3769,14 +3769,14 @@
    *
    * @param scripts the scripts
    */
-  void set scripts(List<HtmlScriptElement> scripts2) {
-    if (scripts2.length == 0) {
-      scripts2 = HtmlScriptElementImpl.EMPTY_ARRAY;
+  void set scripts(List<HtmlScriptElement> scripts) {
+    if (scripts.length == 0) {
+      scripts = HtmlScriptElementImpl.EMPTY_ARRAY;
     }
-    for (HtmlScriptElement script in scripts2) {
+    for (HtmlScriptElement script in scripts) {
       ((script as HtmlScriptElementImpl)).enclosingElement = this;
     }
-    this._scripts = scripts2;
+    this._scripts = scripts;
   }
 
   /**
@@ -3784,8 +3784,8 @@
    *
    * @param source the source that corresponds to this HTML file
    */
-  void set source(Source source2) {
-    this._source = source2;
+  void set source(Source source) {
+    this._source = source;
   }
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -3864,8 +3864,8 @@
    *
    * @param combinators the combinators that were specified as part of the import directive
    */
-  void set combinators(List<NamespaceCombinator> combinators2) {
-    this._combinators = combinators2;
+  void set combinators(List<NamespaceCombinator> combinators) {
+    this._combinators = combinators;
   }
 
   /**
@@ -3874,8 +3874,8 @@
    *
    * @param importedLibrary the library that is imported into this library
    */
-  void set importedLibrary(LibraryElement importedLibrary2) {
-    this._importedLibrary = importedLibrary2;
+  void set importedLibrary(LibraryElement importedLibrary) {
+    this._importedLibrary = importedLibrary;
   }
 
   /**
@@ -3883,8 +3883,8 @@
    *
    * @param prefix the prefix that was specified as part of the import directive
    */
-  void set prefix(PrefixElement prefix2) {
-    this._prefix = prefix2;
+  void set prefix(PrefixElement prefix) {
+    this._prefix = prefix;
   }
 
   /**
@@ -3892,8 +3892,8 @@
    *
    * @param uri the URI that is specified by this directive.
    */
-  void set uri(String uri2) {
-    this._uri = uri2;
+  void set uri(String uri) {
+    this._uri = uri;
   }
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -4030,22 +4030,22 @@
   }
   accept(ElementVisitor visitor) => visitor.visitLibraryElement(this);
   bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && _definingCompilationUnit == ((object as LibraryElementImpl)).definingCompilationUnit;
-  ElementImpl getChild(String identifier2) {
-    if (((_definingCompilationUnit as CompilationUnitElementImpl)).identifier == identifier2) {
+  ElementImpl getChild(String identifier) {
+    if (((_definingCompilationUnit as CompilationUnitElementImpl)).identifier == identifier) {
       return _definingCompilationUnit as CompilationUnitElementImpl;
     }
     for (CompilationUnitElement part in _parts) {
-      if (((part as CompilationUnitElementImpl)).identifier == identifier2) {
+      if (((part as CompilationUnitElementImpl)).identifier == identifier) {
         return part as CompilationUnitElementImpl;
       }
     }
     for (ImportElement importElement in _imports) {
-      if (((importElement as ImportElementImpl)).identifier == identifier2) {
+      if (((importElement as ImportElementImpl)).identifier == identifier) {
         return importElement as ImportElementImpl;
       }
     }
     for (ExportElement exportElement in _exports) {
-      if (((exportElement as ExportElementImpl)).identifier == identifier2) {
+      if (((exportElement as ExportElementImpl)).identifier == identifier) {
         return exportElement as ExportElementImpl;
       }
     }
@@ -4123,9 +4123,9 @@
    *
    * @param definingCompilationUnit the compilation unit that defines this library
    */
-  void set definingCompilationUnit(CompilationUnitElement definingCompilationUnit2) {
-    ((definingCompilationUnit2 as CompilationUnitElementImpl)).enclosingElement = this;
-    this._definingCompilationUnit = definingCompilationUnit2;
+  void set definingCompilationUnit(CompilationUnitElement definingCompilationUnit) {
+    ((definingCompilationUnit as CompilationUnitElementImpl)).enclosingElement = this;
+    this._definingCompilationUnit = definingCompilationUnit;
   }
 
   /**
@@ -4133,8 +4133,8 @@
    *
    * @param entryPoint the entry point for this library
    */
-  void set entryPoint(FunctionElement entryPoint2) {
-    this._entryPoint = entryPoint2;
+  void set entryPoint(FunctionElement entryPoint) {
+    this._entryPoint = entryPoint;
   }
 
   /**
@@ -4142,11 +4142,11 @@
    *
    * @param exports the specifications of all of the exports defined in this library
    */
-  void set exports(List<ExportElement> exports2) {
-    for (ExportElement exportElement in exports2) {
+  void set exports(List<ExportElement> exports) {
+    for (ExportElement exportElement in exports) {
       ((exportElement as ExportElementImpl)).enclosingElement = this;
     }
-    this._exports = exports2;
+    this._exports = exports;
   }
 
   /**
@@ -4154,15 +4154,15 @@
    *
    * @param imports the specifications of all of the imports defined in this library
    */
-  void set imports(List<ImportElement> imports2) {
-    for (ImportElement importElement in imports2) {
+  void set imports(List<ImportElement> imports) {
+    for (ImportElement importElement in imports) {
       ((importElement as ImportElementImpl)).enclosingElement = this;
       PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl;
       if (prefix != null) {
         prefix.enclosingElement = this;
       }
     }
-    this._imports = imports2;
+    this._imports = imports;
   }
 
   /**
@@ -4171,11 +4171,11 @@
    * @param parts the compilation units that are included in this library using a `part`
    *          directive
    */
-  void set parts(List<CompilationUnitElement> parts2) {
-    for (CompilationUnitElement compilationUnit in parts2) {
+  void set parts(List<CompilationUnitElement> parts) {
+    for (CompilationUnitElement compilationUnit in parts) {
       ((compilationUnit as CompilationUnitElementImpl)).enclosingElement = this;
     }
-    this._parts = parts2;
+    this._parts = parts;
   }
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -4593,8 +4593,8 @@
    *
    * @param parameterKind the new kind of this parameter
    */
-  void set parameterKind(ParameterKind parameterKind2) {
-    this._parameterKind = parameterKind2;
+  void set parameterKind(ParameterKind parameterKind) {
+    this._parameterKind = parameterKind;
   }
 
   /**
@@ -4602,11 +4602,11 @@
    *
    * @param parameters the parameters defined by this executable element
    */
-  void set parameters(List<ParameterElement> parameters2) {
-    for (ParameterElement parameter in parameters2) {
+  void set parameters(List<ParameterElement> parameters) {
+    for (ParameterElement parameter in parameters) {
       ((parameter as ParameterElementImpl)).enclosingElement = this;
     }
-    this._parameters = parameters2;
+    this._parameters = parameters;
   }
 
   /**
@@ -4678,16 +4678,17 @@
    *
    * @param importedLibraries the libraries that are imported using this prefix
    */
-  void set importedLibraries(List<LibraryElement> importedLibraries2) {
-    for (LibraryElement library in importedLibraries2) {
+  void set importedLibraries(List<LibraryElement> importedLibraries) {
+    for (LibraryElement library in importedLibraries) {
       ((library as LibraryElementImpl)).enclosingElement = this;
     }
-    this._importedLibraries = importedLibraries2;
+    this._importedLibraries = importedLibraries;
   }
   void appendTo(JavaStringBuilder builder) {
     builder.append("as ");
     super.appendTo(builder);
   }
+  String get identifier => "_${super.identifier}";
 }
 /**
  * Instances of the class `PropertyAccessorElementImpl` implement a
@@ -4797,8 +4798,8 @@
    *
    * @param variable the variable associated with this accessor
    */
-  void set variable(PropertyInducingElement variable2) {
-    this._variable = variable2;
+  void set variable(PropertyInducingElement variable) {
+    this._variable = variable;
   }
   void appendTo(JavaStringBuilder builder) {
     builder.append(isGetter ? "get " : "set ");
@@ -4853,8 +4854,8 @@
    *
    * @param getter the getter associated with this element
    */
-  void set getter(PropertyAccessorElement getter2) {
-    this._getter = getter2;
+  void set getter(PropertyAccessorElement getter) {
+    this._getter = getter;
   }
 
   /**
@@ -4862,8 +4863,8 @@
    *
    * @param setter the setter associated with this element
    */
-  void set setter(PropertyAccessorElement setter2) {
-    this._setter = setter2;
+  void set setter(PropertyAccessorElement setter) {
+    this._setter = setter;
   }
 }
 /**
@@ -4887,8 +4888,8 @@
    *
    * @param shownNames the names that are to be made visible in the importing library
    */
-  void set shownNames(List<String> shownNames2) {
-    this._shownNames = shownNames2;
+  void set shownNames(List<String> shownNames) {
+    this._shownNames = shownNames;
   }
   String toString() {
     JavaStringBuilder builder = new JavaStringBuilder();
@@ -4972,8 +4973,8 @@
    *
    * @param bound the type representing the bound associated with this parameter
    */
-  void set bound(Type2 bound2) {
-    this._bound = bound2;
+  void set bound(Type2 bound) {
+    this._bound = bound;
   }
 
   /**
@@ -4981,8 +4982,8 @@
    *
    * @param type the type defined by this type parameter
    */
-  void set type(TypeParameterType type2) {
-    this._type = type2;
+  void set type(TypeParameterType type) {
+    this._type = type;
   }
   void appendTo(JavaStringBuilder builder) {
     builder.append(displayName);
@@ -5077,11 +5078,11 @@
    *
    * @param initializer the function representing this variable's initializer
    */
-  void set initializer(FunctionElement initializer2) {
-    if (initializer2 != null) {
-      ((initializer2 as FunctionElementImpl)).enclosingElement = this;
+  void set initializer(FunctionElement initializer) {
+    if (initializer != null) {
+      ((initializer as FunctionElementImpl)).enclosingElement = this;
     }
-    this._initializer = initializer2;
+    this._initializer = initializer;
   }
 
   /**
@@ -5089,8 +5090,8 @@
    *
    * @param type the declared type of this variable
    */
-  void set type(Type2 type2) {
-    this._type = type2;
+  void set type(Type2 type) {
+    this._type = type;
   }
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -6013,8 +6014,8 @@
    *
    * @param typeArguments the actual types of the type arguments
    */
-  void set typeArguments(List<Type2> typeArguments2) {
-    this._typeArguments = typeArguments2;
+  void set typeArguments(List<Type2> typeArguments) {
+    this._typeArguments = typeArguments;
   }
   FunctionTypeImpl substitute3(List<Type2> argumentTypes) => substitute2(argumentTypes, typeArguments);
   FunctionTypeImpl substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) {
@@ -6480,24 +6481,24 @@
     return isMoreSpecificThan2(type as InterfaceType, new Set<ClassElement>());
   }
   bool get isObject => element.supertype == null;
-  bool isSubtypeOf(Type2 type2) {
-    if (identical(type2, DynamicTypeImpl.instance)) {
+  bool isSubtypeOf(Type2 type) {
+    if (identical(type, DynamicTypeImpl.instance)) {
       return true;
-    } else if (type2 is TypeParameterType) {
+    } else if (type is TypeParameterType) {
       return true;
-    } else if (type2 is FunctionType) {
+    } else if (type is FunctionType) {
       ClassElement element = this.element;
       MethodElement callMethod = element.lookUpMethod("call", element.library);
       if (callMethod != null) {
-        return callMethod.type.isSubtypeOf(type2);
+        return callMethod.type.isSubtypeOf(type);
       }
       return false;
-    } else if (type2 is! InterfaceType) {
+    } else if (type is! InterfaceType) {
       return false;
-    } else if (this == type2) {
+    } else if (this == type) {
       return true;
     }
-    return isSubtypeOf2(type2 as InterfaceType, new Set<ClassElement>());
+    return isSubtypeOf2(type as InterfaceType, new Set<ClassElement>());
   }
   ConstructorElement lookUpConstructor(String constructorName, LibraryElement library) {
     ConstructorElement constructorElement;
@@ -6619,8 +6620,8 @@
    *
    * @param typeArguments the actual types of the type arguments
    */
-  void set typeArguments(List<Type2> typeArguments2) {
-    this._typeArguments = typeArguments2;
+  void set typeArguments(List<Type2> typeArguments) {
+    this._typeArguments = typeArguments;
   }
   InterfaceTypeImpl substitute4(List<Type2> argumentTypes) => substitute2(argumentTypes, typeArguments);
   InterfaceTypeImpl substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) {
@@ -6659,7 +6660,7 @@
     if (s.isDirectSupertypeOf(this)) {
       return true;
     }
-    ClassElement tElement = element;
+    ClassElement tElement = this.element;
     ClassElement sElement = s.element;
     if (tElement == sElement) {
       List<Type2> tArguments = typeArguments;
@@ -6695,9 +6696,9 @@
     }
     return false;
   }
-  bool isSubtypeOf2(InterfaceType type2, Set<ClassElement> visitedClasses) {
+  bool isSubtypeOf2(InterfaceType type, Set<ClassElement> visitedClasses) {
     InterfaceType typeT = this;
-    InterfaceType typeS = type2;
+    InterfaceType typeS = type;
     ClassElement elementT = element;
     if (elementT == null || visitedClasses.contains(elementT)) {
       return false;
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
index 1d8b5f8..84f6f56 100644
--- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -101,8 +101,8 @@
    * @param logger the logger that should receive information about errors within the analysis
    *          engine
    */
-  void set logger(Logger logger2) {
-    this._logger = logger2 == null ? Logger.NULL : logger2;
+  void set logger(Logger logger) {
+    this._logger = logger == null ? Logger.NULL : logger;
   }
 }
 /**
@@ -1440,10 +1440,10 @@
       return super.getState(descriptor);
     }
   }
-  CacheState getState2(DataDescriptor descriptor, Source librarySource2) {
+  CacheState getState2(DataDescriptor descriptor, Source librarySource) {
     DartEntryImpl_ResolutionState state = _resolutionState;
     while (state != null) {
-      if (librarySource2 == state._librarySource) {
+      if (librarySource == state._librarySource) {
         if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
           return state._resolutionErrorsState;
         } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
@@ -1488,10 +1488,10 @@
     }
     return super.getValue(descriptor);
   }
-  Object getValue2(DataDescriptor descriptor, Source librarySource2) {
+  Object getValue2(DataDescriptor descriptor, Source librarySource) {
     DartEntryImpl_ResolutionState state = _resolutionState;
     while (state != null) {
-      if (librarySource2 == state._librarySource) {
+      if (librarySource == state._librarySource) {
         if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
           return state._resolutionErrors as Object;
         } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
@@ -1676,9 +1676,9 @@
    * @param librarySource the source of the defining compilation unit of the library that used to
    *          contain this part but no longer does
    */
-  void removeResolution(Source librarySource2) {
-    if (librarySource2 != null) {
-      if (librarySource2 == _resolutionState._librarySource) {
+  void removeResolution(Source librarySource) {
+    if (librarySource != null) {
+      if (librarySource == _resolutionState._librarySource) {
         if (_resolutionState._nextState == null) {
           _resolutionState.invalidateAllResolutionInformation();
         } else {
@@ -1688,7 +1688,7 @@
         DartEntryImpl_ResolutionState priorState = _resolutionState;
         DartEntryImpl_ResolutionState state = _resolutionState._nextState;
         while (state != null) {
-          if (librarySource2 == state._librarySource) {
+          if (librarySource == state._librarySource) {
             priorState._nextState = state._nextState;
             break;
           }
@@ -1904,16 +1904,16 @@
    * @param librarySource the library source (not `null`)
    * @return the resolution state (not `null`)
    */
-  DartEntryImpl_ResolutionState getOrCreateResolutionState(Source librarySource2) {
+  DartEntryImpl_ResolutionState getOrCreateResolutionState(Source librarySource) {
     DartEntryImpl_ResolutionState state = _resolutionState;
     if (state._librarySource == null) {
-      state._librarySource = librarySource2;
+      state._librarySource = librarySource;
       return state;
     }
-    while (state._librarySource != librarySource2) {
+    while (state._librarySource != librarySource) {
       if (state._nextState == null) {
         DartEntryImpl_ResolutionState newState = new DartEntryImpl_ResolutionState();
-        newState._librarySource = librarySource2;
+        newState._librarySource = librarySource;
         state._nextState = newState;
         return newState;
       }
@@ -2484,8 +2484,8 @@
    *
    * @param exception the exception that caused one or more values to be uncomputable
    */
-  void set exception(AnalysisException exception2) {
-    this._exception = exception2;
+  void set exception(AnalysisException exception) {
+    this._exception = exception;
   }
 
   /**
@@ -2779,6 +2779,7 @@
     return null;
   }
   List<AnalysisError> computeErrors(Source source) {
+    bool enableHints = analysisOptions.hint;
     SourceEntry sourceEntry = getReadableSourceEntry(source);
     if (sourceEntry is DartEntry) {
       List<AnalysisError> errors = new List<AnalysisError>();
@@ -2787,12 +2788,16 @@
       dartEntry = getReadableDartEntry(source);
       if (identical(dartEntry.getValue(DartEntry.SOURCE_KIND), SourceKind.LIBRARY)) {
         ListUtilities.addAll(errors, getDartResolutionData(source, source, dartEntry, DartEntry.RESOLUTION_ERRORS));
-        ListUtilities.addAll(errors, getDartHintData(source, source, dartEntry, DartEntry.HINTS));
+        if (enableHints) {
+          ListUtilities.addAll(errors, getDartHintData(source, source, dartEntry, DartEntry.HINTS));
+        }
       } else {
         List<Source> libraries = getLibrariesContaining(source);
         for (Source librarySource in libraries) {
           ListUtilities.addAll(errors, getDartResolutionData(source, librarySource, dartEntry, DartEntry.RESOLUTION_ERRORS));
-          ListUtilities.addAll(errors, getDartHintData(source, librarySource, dartEntry, DartEntry.HINTS));
+          if (enableHints) {
+            ListUtilities.addAll(errors, getDartHintData(source, librarySource, dartEntry, DartEntry.HINTS));
+          }
         }
       }
       if (errors.isEmpty) {
@@ -3305,9 +3310,9 @@
   }
   CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) => getDartResolutionData2(unitSource, librarySource, DartEntry.RESOLVED_UNIT, null);
   HtmlUnit resolveHtmlUnit(Source htmlSource) => parseHtmlUnit(htmlSource);
-  void set analysisOptions(AnalysisOptions options2) {
+  void set analysisOptions(AnalysisOptions options) {
     {
-      this._options = options2;
+      this._options = options;
       invalidateAllResolutionInformation();
     }
   }
@@ -3983,11 +3988,11 @@
    * @param kind the kind of sources to be returned
    * @return all of the sources known to this context that have the given kind
    */
-  List<Source> getSources(SourceKind kind2) {
+  List<Source> getSources(SourceKind kind) {
     List<Source> sources = new List<Source>();
     {
       for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) {
-        if (identical(entry.getValue().kind, kind2)) {
+        if (identical(entry.getValue().kind, kind)) {
           sources.add(entry.getKey());
         }
       }
@@ -4102,7 +4107,7 @@
    */
   DartEntry recordGenerateDartHintsTask(GenerateDartHintsTask task) {
     Source librarySource = task.libraryElement.source;
-    AnalysisException thrownException = task.thrownException;
+    AnalysisException thrownException = task.exception;
     DartEntry libraryEntry = null;
     Map<Source, TimestampedData<List<AnalysisError>>> hintMap = task.hintMap;
     if (hintMap == null) {
@@ -4186,7 +4191,7 @@
    */
   DartEntry recordParseDartTaskResults(ParseDartTask task) {
     Source source = task.source;
-    AnalysisException thrownException = task.thrownException;
+    AnalysisException thrownException = task.exception;
     DartEntry dartEntry = null;
     {
       SourceEntry sourceEntry = _cache.get(source);
@@ -4253,7 +4258,7 @@
    */
   HtmlEntry recordParseHtmlTaskResults(ParseHtmlTask task) {
     Source source = task.source;
-    AnalysisException thrownException = task.thrownException;
+    AnalysisException thrownException = task.exception;
     HtmlEntry htmlEntry = null;
     {
       SourceEntry sourceEntry = _cache.get(source);
@@ -4327,7 +4332,7 @@
    */
   DartEntry recordResolveDartLibraryTaskResults(ResolveDartLibraryTask task) {
     LibraryResolver resolver = task.libraryResolver;
-    AnalysisException thrownException = task.thrownException;
+    AnalysisException thrownException = task.exception;
     DartEntry unitEntry = null;
     Source unitSource = task.unitSource;
     if (resolver != null) {
@@ -4419,7 +4424,7 @@
   SourceEntry recordResolveDartUnitTaskResults(ResolveDartUnitTask task) {
     Source unitSource = task.source;
     Source librarySource = task.librarySource;
-    AnalysisException thrownException = task.thrownException;
+    AnalysisException thrownException = task.exception;
     DartEntry dartEntry = null;
     {
       SourceEntry sourceEntry = _cache.get(unitSource);
@@ -4477,7 +4482,7 @@
    */
   SourceEntry recordResolveHtmlTaskResults(ResolveHtmlTask task) {
     Source source = task.source;
-    AnalysisException thrownException = task.thrownException;
+    AnalysisException thrownException = task.exception;
     HtmlEntry htmlEntry = null;
     {
       SourceEntry sourceEntry = _cache.get(source);
@@ -4700,8 +4705,8 @@
    *
    * @param hint `true` if analysis is to generate hint results
    */
-  void set hint(bool hint2) {
-    this._hint = hint2;
+  void set hint(bool hint) {
+    this._hint = hint;
   }
 
   /**
@@ -4794,8 +4799,8 @@
    *
    * @param compilationUnit the fully resolved AST that changed as a result of the analysis
    */
-  void set compilationUnit(CompilationUnit compilationUnit2) {
-    this._compilationUnit = compilationUnit2;
+  void set compilationUnit(CompilationUnit compilationUnit) {
+    this._compilationUnit = compilationUnit;
   }
 
   /**
@@ -4805,9 +4810,9 @@
    * @param errors the errors that changed as a result of the analysis
    * @param lineInfo the line information associated with the source
    */
-  void setErrors(List<AnalysisError> errors2, LineInfo lineInfo2) {
-    this._errors = errors2;
-    this._lineInfo = lineInfo2;
+  void setErrors(List<AnalysisError> errors, LineInfo lineInfo) {
+    this._errors = errors;
+    this._lineInfo = lineInfo;
   }
 }
 /**
@@ -5927,7 +5932,7 @@
    * The exception that was thrown while performing this task, or `null` if the task completed
    * successfully.
    */
-  AnalysisException thrownException;
+  AnalysisException exception;
 
   /**
    * Initialize a newly created task to perform analysis within the given context.
@@ -5958,7 +5963,7 @@
     try {
       safelyPerform();
     } on AnalysisException catch (exception) {
-      thrownException = exception;
+      this.exception = exception;
       AnalysisEngine.instance.logger.logInformation2("Task failed: ${taskDescription}", exception);
     }
     return accept(visitor);
@@ -6325,14 +6330,14 @@
   RecordingErrorListener errorListener;
   List<Token> token;
   Source_ContentReceiver_9(this.ParseDartTask_this, this.errorListener, this.token);
-  void accept(CharBuffer contents, int modificationTime2) {
-    ParseDartTask_this.modificationTime = modificationTime2;
+  void accept(CharBuffer contents, int modificationTime) {
+    ParseDartTask_this.modificationTime = modificationTime;
     CharBufferScanner scanner = new CharBufferScanner(ParseDartTask_this.source, contents, errorListener);
     token[0] = scanner.tokenize();
     ParseDartTask_this.lineInfo = new LineInfo(scanner.lineStarts);
   }
-  void accept2(String contents, int modificationTime2) {
-    ParseDartTask_this.modificationTime = modificationTime2;
+  void accept2(String contents, int modificationTime) {
+    ParseDartTask_this.modificationTime = modificationTime;
     StringScanner scanner = new StringScanner(ParseDartTask_this.source, contents, errorListener);
     token[0] = scanner.tokenize();
     ParseDartTask_this.lineInfo = new LineInfo(scanner.lineStarts);
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart
index b57ab78..7c5d24d 100644
--- a/pkg/analyzer_experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -206,8 +206,8 @@
    *
    * @param source the source to be used when reporting errors
    */
-  void set source(Source source2) {
-    this._source = source2 == null ? _defaultSource : source2;
+  void set source(Source source) {
+    this._source = source == null ? _defaultSource : source;
   }
 }
 /**
@@ -478,24 +478,68 @@
   static final HintCode TYPE_CHECK_IS_NULL = new HintCode.con1('TYPE_CHECK_IS_NULL', 12, "Tests for null should be done with '== null'");
 
   /**
+   * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_GETTER] or
+   * [StaticWarningCode#UNDEFINED_GETTER] would have been generated, if we used propagated
+   * information for the warnings.
+   *
+   * @param getterName the name of the getter
+   * @param enclosingType the name of the enclosing type where the getter is being looked for
+   * @see StaticTypeWarningCode#UNDEFINED_GETTER
+   * @see StaticWarningCode#UNDEFINED_GETTER
+   */
+  static final HintCode UNDEFINED_GETTER = new HintCode.con1('UNDEFINED_GETTER', 13, StaticTypeWarningCode.UNDEFINED_GETTER.message);
+
+  /**
+   * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_METHOD] would
+   * have been generated, if we used propagated information for the warnings.
+   *
+   * @param methodName the name of the method that is undefined
+   * @param typeName the resolved type name that the method lookup is happening on
+   * @see StaticTypeWarningCode#UNDEFINED_METHOD
+   */
+  static final HintCode UNDEFINED_METHOD = new HintCode.con1('UNDEFINED_METHOD', 14, StaticTypeWarningCode.UNDEFINED_METHOD.message);
+
+  /**
+   * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_OPERATOR]
+   * would have been generated, if we used propagated information for the warnings.
+   *
+   * @param operator the name of the operator
+   * @param enclosingType the name of the enclosing type where the operator is being looked for
+   * @see StaticTypeWarningCode#UNDEFINED_OPERATOR
+   */
+  static final HintCode UNDEFINED_OPERATOR = new HintCode.con1('UNDEFINED_OPERATOR', 15, StaticTypeWarningCode.UNDEFINED_OPERATOR.message);
+
+  /**
+   * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_SETTER] or
+   * [StaticWarningCode#UNDEFINED_SETTER] would have been generated, if we used propagated
+   * information for the warnings.
+   *
+   * @param setterName the name of the setter
+   * @param enclosingType the name of the enclosing type where the setter is being looked for
+   * @see StaticTypeWarningCode#UNDEFINED_SETTER
+   * @see StaticWarningCode#UNDEFINED_SETTER
+   */
+  static final HintCode UNDEFINED_SETTER = new HintCode.con1('UNDEFINED_SETTER', 16, StaticTypeWarningCode.UNDEFINED_SETTER.message);
+
+  /**
    * Unnecessary cast.
    */
-  static final HintCode UNNECESSARY_CAST = new HintCode.con1('UNNECESSARY_CAST', 13, "Unnecessary cast");
+  static final HintCode UNNECESSARY_CAST = new HintCode.con1('UNNECESSARY_CAST', 17, "Unnecessary cast");
 
   /**
    * Unnecessary type checks, the result is always true.
    */
-  static final HintCode UNNECESSARY_TYPE_CHECK_FALSE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_FALSE', 14, "Unnecessary type check, the result is always false");
+  static final HintCode UNNECESSARY_TYPE_CHECK_FALSE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_FALSE', 18, "Unnecessary type check, the result is always false");
 
   /**
    * Unnecessary type checks, the result is always false.
    */
-  static final HintCode UNNECESSARY_TYPE_CHECK_TRUE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_TRUE', 15, "Unnecessary type check, the result is always true");
+  static final HintCode UNNECESSARY_TYPE_CHECK_TRUE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_TRUE', 19, "Unnecessary type check, the result is always true");
 
   /**
    * Unused imports are imports which are never not used.
    */
-  static final HintCode UNUSED_IMPORT = new HintCode.con1('UNUSED_IMPORT', 16, "Unused import");
+  static final HintCode UNUSED_IMPORT = new HintCode.con1('UNUSED_IMPORT', 20, "Unused import");
   static final List<HintCode> values = [
       DEAD_CODE,
       DEAD_CODE_CATCH_FOLLOWING_CATCH,
@@ -510,6 +554,10 @@
       OVERRIDE_EQUALS_BUT_NOT_HASH_CODE,
       TYPE_CHECK_IS_NOT_NULL,
       TYPE_CHECK_IS_NULL,
+      UNDEFINED_GETTER,
+      UNDEFINED_METHOD,
+      UNDEFINED_OPERATOR,
+      UNDEFINED_SETTER,
       UNNECESSARY_CAST,
       UNNECESSARY_TYPE_CHECK_FALSE,
       UNNECESSARY_TYPE_CHECK_TRUE,
@@ -2793,6 +2841,8 @@
    * <i>id</i> occurs inside a top level or static function (be it function, method, getter, or
    * setter) or variable initializer and there is no declaration <i>d</i> with name <i>id</i> in the
    * lexical scope enclosing the expression.
+   *
+   * @param name the name of the identifier
    */
   static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode.con1('UNDEFINED_IDENTIFIER', 72, "Undefined name '%s'");
 
diff --git a/pkg/analyzer_experimental/lib/src/generated/html.dart b/pkg/analyzer_experimental/lib/src/generated/html.dart
index a6c4a4e..f5286bc 100644
--- a/pkg/analyzer_experimental/lib/src/generated/html.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/html.dart
@@ -210,7 +210,7 @@
     if (beginToken == null) {
       return -1;
     }
-    return beginToken.offset;
+    return this.beginToken.offset;
   }
 
   /**
@@ -397,8 +397,8 @@
   /**
    * Set array of element tags for which the content between tags should be consider a single token.
    */
-  void set passThroughElements(List<String> passThroughElements2) {
-    this._passThroughElements = passThroughElements2 != null ? passThroughElements2 : _NO_PASS_THROUGH_ELEMENTS;
+  void set passThroughElements(List<String> passThroughElements) {
+    this._passThroughElements = passThroughElements != null ? passThroughElements : _NO_PASS_THROUGH_ELEMENTS;
   }
 
   /**
@@ -694,8 +694,8 @@
     this._charOffset = -1;
   }
   int get offset => _charOffset;
-  void set offset(int offset2) {
-    _charOffset = offset2;
+  void set offset(int offset) {
+    _charOffset = offset;
   }
   int advance() {
     if (++_charOffset < _stringLength) {
@@ -999,14 +999,14 @@
   HtmlScanner(Source source) {
     this._source = source;
   }
-  void accept(CharBuffer contents, int modificationTime2) {
-    this._modificationTime = modificationTime2;
+  void accept(CharBuffer contents, int modificationTime) {
+    this._modificationTime = modificationTime;
     _scanner = new CharBufferScanner(_source, contents);
     _scanner.passThroughElements = _SCRIPT_TAG;
     _token = _scanner.tokenize();
   }
-  void accept2(String contents, int modificationTime2) {
-    this._modificationTime = modificationTime2;
+  void accept2(String contents, int modificationTime) {
+    this._modificationTime = modificationTime;
     _scanner = new StringScanner(_source, contents);
     _scanner.passThroughElements = _SCRIPT_TAG;
     _token = _scanner.tokenize();
@@ -1354,9 +1354,9 @@
    * @param name the attribute name
    * @return the attribute or `null` if no matching attribute is found
    */
-  XmlAttributeNode getAttribute(String name2) {
+  XmlAttributeNode getAttribute(String name) {
     for (XmlAttributeNode attribute in attributes) {
-      if (attribute.name.lexeme == name2) {
+      if (attribute.name.lexeme == name) {
         return attribute;
       }
     }
diff --git a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
index 8af2198..32f7498 100644
--- a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
@@ -85,8 +85,8 @@
    *
    * @param logger the logger that should receive instrumentation information
    */
-  static void set logger(InstrumentationLogger logger2) {
-    _CURRENT_LOGGER = logger2 == null ? _NULL_LOGGER : logger2;
+  static void set logger(InstrumentationLogger logger) {
+    _CURRENT_LOGGER = logger == null ? _NULL_LOGGER : logger;
   }
 }
 class InstrumentationBuilder_15 implements InstrumentationBuilder {
diff --git a/pkg/analyzer_experimental/lib/src/generated/parser.dart b/pkg/analyzer_experimental/lib/src/generated/parser.dart
index 2264972..a7cb7de 100644
--- a/pkg/analyzer_experimental/lib/src/generated/parser.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/parser.dart
@@ -259,8 +259,8 @@
       instrumentation.log();
     }
   }
-  void set currentToken(Token currentToken2) {
-    this._currentToken = currentToken2;
+  void set currentToken(Token currentToken) {
+    this._currentToken = currentToken;
   }
 
   /**
@@ -818,7 +818,7 @@
    * @param keyword the keyword that is being tested for
    * @return `true` if the given token matches the given keyword
    */
-  bool matches3(Token token, Keyword keyword2) => identical(token.type, TokenType.KEYWORD) && identical(((token as KeywordToken)).keyword, keyword2);
+  bool matches3(Token token, Keyword keyword) => identical(token.type, TokenType.KEYWORD) && identical(((token as KeywordToken)).keyword, keyword);
 
   /**
    * Return `true` if the given token has the given type.
@@ -827,7 +827,7 @@
    * @param type the type of token that is being tested for
    * @return `true` if the given token has the given type
    */
-  bool matches4(Token token, TokenType type2) => identical(token.type, type2);
+  bool matches4(Token token, TokenType type) => identical(token.type, type);
 
   /**
    * Return `true` if the current token has the given type. Note that this method, unlike
@@ -838,10 +838,10 @@
    * @param type the type of token that can optionally appear in the current location
    * @return `true` if the current token has the given type
    */
-  bool matches5(TokenType type2) {
+  bool matches5(TokenType type) {
     TokenType currentType = _currentToken.type;
-    if (currentType != type2) {
-      if (identical(type2, TokenType.GT)) {
+    if (currentType != type) {
+      if (identical(type, TokenType.GT)) {
         if (identical(currentType, TokenType.GT_GT)) {
           int offset = _currentToken.offset;
           Token first = new Token(TokenType.GT, offset);
@@ -4861,8 +4861,7 @@
     if (matcher.find()) {
       int offset = commentToken.offset + matcher.start() + matcher.group(1).length;
       int length = matcher.group(2).length;
-      // TODO(scheglov) analyzer_experimental users don't expect it
-//      _errorListener.onError(new AnalysisError.con2(_source, offset, length, TodoCode.TODO, [matcher.group(2)]));
+      // _errorListener.onError(new AnalysisError.con2(_source, offset, length, TodoCode.TODO, [matcher.group(2)]));
     }
   }
 
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
index 3860b21..535ce2e 100644
--- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -33,7 +33,7 @@
    * @return the compilation unit element that was built
    * @throws AnalysisException if the analysis could not be performed
    */
-  CompilationUnitElementImpl buildCompilationUnit(Source source2, CompilationUnit unit) {
+  CompilationUnitElementImpl buildCompilationUnit(Source source, CompilationUnit unit) {
     TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.start();
     if (unit == null) {
       return null;
@@ -41,10 +41,10 @@
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
     unit.accept(builder);
-    CompilationUnitElementImpl element = new CompilationUnitElementImpl(source2.shortName);
+    CompilationUnitElementImpl element = new CompilationUnitElementImpl(source.shortName);
     element.accessors = holder.accessors;
     element.functions = holder.functions;
-    element.source = source2;
+    element.source = source;
     element.typeAliases = holder.typeAliases;
     element.types = holder.types;
     element.topLevelVariables = holder.topLevelVariables;
@@ -693,7 +693,7 @@
    * @param keyword the keyword being tested for
    * @return `true` if the given token is a token for the given keyword
    */
-  bool matches(sc.Token token, sc.Keyword keyword2) => token != null && identical(token.type, sc.TokenType.KEYWORD) && identical(((token as sc.KeywordToken)).keyword, keyword2);
+  bool matches(sc.Token token, sc.Keyword keyword) => token != null && identical(token.type, sc.TokenType.KEYWORD) && identical(((token as sc.KeywordToken)).keyword, keyword);
 
   /**
    * Sets the visible source range for formal parameter.
@@ -1117,11 +1117,11 @@
    * @param unit the AST structure representing the HTML
    * @throws AnalysisException if the analysis could not be performed
    */
-  HtmlElementImpl buildHtmlElement2(Source source2, int modificationStamp2, ht.HtmlUnit unit) {
-    this._modificationStamp = modificationStamp2;
-    _lineInfo = _context.computeLineInfo(source2);
-    HtmlElementImpl result = new HtmlElementImpl(_context, source2.shortName);
-    result.source = source2;
+  HtmlElementImpl buildHtmlElement2(Source source, int modificationStamp, ht.HtmlUnit unit) {
+    this._modificationStamp = modificationStamp;
+    _lineInfo = _context.computeLineInfo(source);
+    HtmlElementImpl result = new HtmlElementImpl(_context, source.shortName);
+    result.source = source;
     _htmlElement = result;
     unit.accept(this);
     _htmlElement = null;
@@ -1296,7 +1296,6 @@
   static String _HASHCODE_GETTER_NAME = "hashCode";
   static String _METHOD = "method";
   static String _NULL_TYPE_NAME = "Null";
-  static String _OBJECT_TYPE_NAME = "Object";
   static String _SETTER = "setter";
   static String _TO_INT_METHOD_NAME = "toInt";
 
@@ -1394,7 +1393,7 @@
     Element rhsElement = rhsType.element;
     LibraryElement libraryElement = rhsElement != null ? rhsElement.library : null;
     if (libraryElement != null && libraryElement.isDartCore) {
-      if ((rhsType.isObject && rhsNameStr == _OBJECT_TYPE_NAME) || (expression is NullLiteral && rhsNameStr == _NULL_TYPE_NAME)) {
+      if (rhsType.isObject || (expression is NullLiteral && rhsNameStr == _NULL_TYPE_NAME)) {
         if (node.notOperator == null) {
           _errorReporter.reportError2(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node, []);
         } else {
@@ -2055,9 +2054,18 @@
     }
     return super.visitCompilationUnit(node);
   }
-  Object visitExportDirective(ExportDirective node) => null;
-  Object visitImportDirective(ImportDirective node) => null;
-  Object visitLibraryDirective(LibraryDirective node) => null;
+  Object visitExportDirective(ExportDirective node) {
+    visitMetadata(node.metadata);
+    return null;
+  }
+  Object visitImportDirective(ImportDirective node) {
+    visitMetadata(node.metadata);
+    return null;
+  }
+  Object visitLibraryDirective(LibraryDirective node) {
+    visitMetadata(node.metadata);
+    return null;
+  }
   Object visitPrefixedIdentifier(PrefixedIdentifier node) {
     SimpleIdentifier prefixIdentifier = node.prefix;
     Element element = prefixIdentifier.staticElement;
@@ -2068,8 +2076,8 @@
     return visitIdentifier(element, prefixIdentifier.name);
   }
   Object visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node.staticElement, node.name);
-  void set inDefiningCompilationUnit(bool inDefiningCompilationUnit2) {
-    this._inDefiningCompilationUnit = inDefiningCompilationUnit2;
+  void set inDefiningCompilationUnit(bool inDefiningCompilationUnit) {
+    this._inDefiningCompilationUnit = inDefiningCompilationUnit;
   }
 
   /**
@@ -2159,6 +2167,20 @@
     }
     return null;
   }
+
+  /**
+   * Given some [NodeList] of [Annotation]s, ensure that the identifiers are visited by
+   * this visitor. Specifically, this covers the cases where AST nodes don't have their identifiers
+   * visited by this visitor, but still need their annotations visited.
+   *
+   * @param annotations the list of annotations to visit
+   */
+  void visitMetadata(NodeList<Annotation> annotations) {
+    for (Annotation annotation in annotations) {
+      Identifier name = annotation.name;
+      visitIdentifier(name.staticElement, name.name);
+    }
+  }
 }
 /**
  * Instances of the class `PubVerifier` traverse an AST structure looking for deviations from
@@ -2354,9 +2376,9 @@
    * @param unit the compilation unit to be resolved
    * @param element the root of the element model used to resolve the AST nodes
    */
-  void resolve(CompilationUnit unit, CompilationUnitElement element2) {
-    _enclosingUnit = element2;
-    unit.element = element2;
+  void resolve(CompilationUnit unit, CompilationUnitElement element) {
+    _enclosingUnit = element;
+    unit.element = element;
     unit.accept(this);
   }
   Object visitCatchClause(CatchClause node) {
@@ -2714,9 +2736,9 @@
    *          for
    * @return the export element whose library has the given source
    */
-  ExportElement find5(List<ExportElement> exports, Source source2) {
+  ExportElement find5(List<ExportElement> exports, Source source) {
     for (ExportElement export in exports) {
-      if (export.exportedLibrary.source == source2) {
+      if (export.exportedLibrary.source == source) {
         return export;
       }
     }
@@ -2733,16 +2755,16 @@
    * @param prefix the prefix with which the library was imported
    * @return the import element whose library has the given source and prefix
    */
-  ImportElement find6(List<ImportElement> imports, Source source2, SimpleIdentifier prefix2) {
+  ImportElement find6(List<ImportElement> imports, Source source, SimpleIdentifier prefix) {
     for (ImportElement element in imports) {
-      if (element.importedLibrary.source == source2) {
+      if (element.importedLibrary.source == source) {
         PrefixElement prefixElement = element.prefix;
-        if (prefix2 == null) {
+        if (prefix == null) {
           if (prefixElement == null) {
             return element;
           }
         } else {
-          if (prefixElement != null && prefix2.name == prefixElement.displayName) {
+          if (prefixElement != null && prefix.name == prefixElement.displayName) {
             return element;
           }
         }
@@ -2919,6 +2941,11 @@
   bool _strictMode = false;
 
   /**
+   * A flag indicating whether we should generate hints.
+   */
+  bool _enableHints = false;
+
+  /**
    * The type representing the type 'dynamic'.
    */
   Type2 _dynamicType;
@@ -2947,7 +2974,9 @@
    */
   ElementResolver(ResolverVisitor resolver) {
     this._resolver = resolver;
-    _strictMode = resolver.definingLibrary.context.analysisOptions.strictMode;
+    AnalysisOptions options = resolver.definingLibrary.context.analysisOptions;
+    _strictMode = options.strictMode;
+    _enableHints = options.hint;
     _dynamicType = resolver.typeProvider.dynamicType;
     _typeType = resolver.typeProvider.typeType;
   }
@@ -2965,8 +2994,13 @@
         Type2 propagatedType = getPropagatedType(leftHandSide);
         MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedType, methodName);
         node.propagatedElement = propagatedMethod;
-        if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
-          _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_METHOD, operator, [methodName, staticType.displayName]);
+        bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
+        bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+        if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
+          ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_METHOD : HintCode.UNDEFINED_METHOD) as ErrorCode;
+          _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [
+              methodName,
+              shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
         }
       }
     }
@@ -2984,8 +3018,13 @@
         Type2 propagatedType = getPropagatedType(leftOperand);
         MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedType, methodName);
         node.propagatedElement = propagatedMethod;
-        if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
-          _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
+        bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
+        bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+        if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
+          ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
+          _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [
+              methodName,
+              shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
         }
       }
     }
@@ -3311,7 +3350,15 @@
         argumentList.correspondingPropagatedParameters = parameters;
       }
     }
-    ErrorCode errorCode = checkForInvocationError(target, staticElement);
+    ErrorCode errorCode = checkForInvocationError(target, true, staticElement);
+    bool generatedWithTypePropagation = false;
+    if (_enableHints && errorCode == null && staticElement == null) {
+      errorCode = checkForInvocationError(target, false, propagatedElement);
+      generatedWithTypePropagation = true;
+    }
+    if (errorCode == null) {
+      return null;
+    }
     if (identical(errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION)) {
       _resolver.reportError5(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName, [methodName.name]);
     } else if (identical(errorCode, CompileTimeErrorCode.UNDEFINED_FUNCTION)) {
@@ -3321,20 +3368,27 @@
       if (target == null) {
         ClassElement enclosingClass = _resolver.enclosingClass;
         targetTypeName = enclosingClass.displayName;
-        _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingClass, StaticTypeWarningCode.UNDEFINED_METHOD, methodName, [methodName.name, targetTypeName]);
+        ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDEFINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode;
+        _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingClass, proxyErrorCode, methodName, [methodName.name, targetTypeName]);
       } else {
-        Type2 targetType = getStaticType(target);
+        Type2 targetType = null;
+        if (!generatedWithTypePropagation) {
+          targetType = getStaticType(target);
+        } else {
+          targetType = getPropagatedType(target);
+          if (targetType == null) {
+            targetType = getStaticType(target);
+          }
+        }
         if (targetType != null && targetType.isDartCoreFunction && methodName.name == CALL_METHOD_NAME) {
           return null;
         }
         targetTypeName = targetType == null ? null : targetType.displayName;
-        _resolver.reportErrorProxyConditionalAnalysisError(targetType.element, StaticTypeWarningCode.UNDEFINED_METHOD, methodName, [methodName.name, targetTypeName]);
+        ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDEFINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode;
+        _resolver.reportErrorProxyConditionalAnalysisError(targetType.element, proxyErrorCode, methodName, [methodName.name, targetTypeName]);
       }
     } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) {
-      Type2 targetType = getPropagatedType(target);
-      if (targetType == null) {
-        targetType = getStaticType(target);
-      }
+      Type2 targetType = getStaticType(target);
       String targetTypeName = targetType == null ? null : targetType.name;
       _resolver.reportError5(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, methodName, [methodName.name, targetTypeName]);
     }
@@ -3357,8 +3411,13 @@
     Type2 propagatedType = getPropagatedType(operand);
     MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName);
     node.propagatedElement = propagatedMethod;
-    if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
-      _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [methodName, staticType.displayName]);
+    bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
+    bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : 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, [
+          methodName,
+          shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
     }
     return null;
   }
@@ -3415,8 +3474,13 @@
       Type2 propagatedType = getPropagatedType(operand);
       MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName);
       node.propagatedElement = propagatedMethod;
-      if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
-        _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
+      bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
+      bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+      if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
+        ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
+        _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [
+            methodName,
+            shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
       }
     }
     return null;
@@ -3573,10 +3637,11 @@
    * reported, or `null` if no error should be reported.
    *
    * @param target the target of the invocation, or `null` if there was no target
+   * @param useStaticContext
    * @param element the element to be invoked
    * @return the error code that should be reported
    */
-  ErrorCode checkForInvocationError(Expression target, Element element) {
+  ErrorCode checkForInvocationError(Expression target, bool useStaticContext, Element element) {
     if (element is PrefixElement) {
       element = null;
     }
@@ -3618,7 +3683,15 @@
             return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
           }
         } else {
-          Type2 targetType = getStaticType(target);
+          Type2 targetType;
+          if (useStaticContext) {
+            targetType = getStaticType(target);
+          } else {
+            targetType = getPropagatedType(target);
+            if (targetType == null) {
+              targetType = getStaticType(target);
+            }
+          }
           if (targetType == null) {
             return CompileTimeErrorCode.UNDEFINED_FUNCTION;
           } else if (!targetType.isDynamic) {
@@ -3641,15 +3714,22 @@
    * @return `true` if and only if an error code is generated on the passed node
    */
   bool checkForUndefinedIndexOperator(IndexExpression node, Expression target, String methodName, MethodElement staticMethod, MethodElement propagatedMethod, Type2 staticType, Type2 propagatedType) {
-    if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
+    bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
+    bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
+    if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
       sc.Token leftBracket = node.leftBracket;
       sc.Token rightBracket = node.rightBracket;
+      ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
       if (leftBracket == null || rightBracket == null) {
-        _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, node, [methodName, staticType.displayName]);
+        _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, node, [
+            methodName,
+            shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
       } else {
         int offset = leftBracket.offset;
         int length = rightBracket.offset - offset + 1;
-        _resolver.reportErrorProxyConditionalAnalysisError2(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, offset, length, [methodName, staticType.displayName]);
+        _resolver.reportErrorProxyConditionalAnalysisError2(staticType.element, errorCode, offset, length, [
+            methodName,
+            shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
       }
       return true;
     }
@@ -3665,9 +3745,9 @@
    * @param executableElement the element that will be invoked with the arguments
    * @return the parameters that correspond to the arguments
    */
-  List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentList, Element element2) {
-    if (element2 is PropertyAccessorElement) {
-      FunctionType getterType = ((element2 as PropertyAccessorElement)).type;
+  List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentList, Element element) {
+    if (element is PropertyAccessorElement) {
+      FunctionType getterType = ((element as PropertyAccessorElement)).type;
       if (getterType != null) {
         Type2 getterReturnType = getterType.returnType;
         if (getterReturnType is InterfaceType) {
@@ -3682,10 +3762,10 @@
           }
         }
       }
-    } else if (element2 is ExecutableElement) {
-      return resolveArgumentsToParameters(false, argumentList, element2 as ExecutableElement);
-    } else if (element2 is VariableElement) {
-      VariableElement variable = element2 as VariableElement;
+    } else if (element is ExecutableElement) {
+      return resolveArgumentsToParameters(false, argumentList, element as ExecutableElement);
+    } else if (element is VariableElement) {
+      VariableElement variable = element as VariableElement;
       Type2 type = variable.type;
       if (type is FunctionType) {
         FunctionType functionType = type as FunctionType;
@@ -4262,9 +4342,9 @@
    * @param nameNode the name of the invoked constructor, may be `null` if unnamed constructor
    *          or not a constructor invocation
    */
-  void resolveAnnotationElement(Annotation annotation, Element element2, SimpleIdentifier nameNode) {
-    if (element2 is PropertyAccessorElement) {
-      PropertyAccessorElement accessorElement = element2 as PropertyAccessorElement;
+  void resolveAnnotationElement(Annotation annotation, Element element, SimpleIdentifier nameNode) {
+    if (element is PropertyAccessorElement) {
+      PropertyAccessorElement accessorElement = element as PropertyAccessorElement;
       if (!accessorElement.isSynthetic) {
         _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotation, []);
         return;
@@ -4275,14 +4355,14 @@
       }
       return;
     }
-    if (element2 is ClassElement) {
+    if (element is ClassElement) {
       if (nameNode == null) {
         nameNode = annotation.constructorName;
       }
       String name = nameNode != null ? nameNode.name : null;
       ConstructorElement constructor;
       {
-        InterfaceType interfaceType = new InterfaceTypeImpl.con1(element2 as ClassElement);
+        InterfaceType interfaceType = new InterfaceTypeImpl.con1(element as ClassElement);
         LibraryElement definingLibrary = _resolver.definingLibrary;
         constructor = interfaceType.lookUpConstructor(name, definingLibrary);
       }
@@ -4297,7 +4377,7 @@
       resolveAnnotationConstructorInvocationArguments(annotation, constructor);
       return;
     }
-    if (element2 != null) {
+    if (element != null) {
       _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotation, []);
     }
   }
@@ -4507,20 +4587,34 @@
     Type2 propagatedType = getPropagatedType(target);
     ExecutableElement propagatedElement = resolveProperty(target, propagatedType, propertyName);
     propertyName.propagatedElement = propagatedElement;
-    if (shouldReportMissingMember(staticType, staticElement) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedElement))) {
+    bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticElement) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedElement));
+    bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedElement) : false;
+    if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) {
       Element selectedElement = select(staticElement, propagatedElement);
       bool isStaticProperty = isStatic(selectedElement);
       if (propertyName.inSetterContext()) {
         if (isStaticProperty) {
-          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticWarningCode.UNDEFINED_SETTER, propertyName, [propertyName.name, staticType.displayName]);
+          ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarningCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode;
+          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [
+              propertyName.name,
+              shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
         } else {
-          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_SETTER, propertyName, [propertyName.name, staticType.displayName]);
+          ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode;
+          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [
+              propertyName.name,
+              shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
         }
       } else if (propertyName.inGetterContext()) {
         if (isStaticProperty) {
-          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticWarningCode.UNDEFINED_GETTER, propertyName, [propertyName.name, staticType.displayName]);
+          ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarningCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
+          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [
+              propertyName.name,
+              shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
         } else {
-          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_GETTER, propertyName, [propertyName.name, staticType.displayName]);
+          ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
+          _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [
+              propertyName.name,
+              shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]);
         }
       } else {
         _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, [propertyName.name]);
@@ -4811,8 +4905,8 @@
    *
    * @param library the new library element
    */
-  void set libraryElement(LibraryElement library2) {
-    this._library = library2;
+  void set libraryElement(LibraryElement library) {
+    this._library = library;
   }
 
   /**
@@ -5353,7 +5447,7 @@
       try {
         _libraryElement = _analysisContext.computeLibraryElement(librarySource) as LibraryElementImpl;
       } on AnalysisException catch (exception) {
-        AnalysisEngine.instance.logger.logError2("Could not compute ilbrary element for ${librarySource.fullName}", exception);
+        AnalysisEngine.instance.logger.logError2("Could not compute library element for ${librarySource.fullName}", exception);
       }
     }
     return _libraryElement;
@@ -5439,8 +5533,8 @@
    *
    * @param exportedLibraries the libraries that are exported by this library
    */
-  void set exportedLibraries(List<Library> exportedLibraries2) {
-    this.exports = exportedLibraries2;
+  void set exportedLibraries(List<Library> exportedLibraries) {
+    this.exports = exportedLibraries;
   }
 
   /**
@@ -5448,8 +5542,8 @@
    *
    * @param importedLibraries the libraries that are imported into this library
    */
-  void set importedLibraries(List<Library> importedLibraries2) {
-    this.imports = importedLibraries2;
+  void set importedLibraries(List<Library> importedLibraries) {
+    this.imports = importedLibraries;
   }
 
   /**
@@ -5457,10 +5551,10 @@
    *
    * @param libraryElement the library element representing this library
    */
-  void set libraryElement(LibraryElementImpl libraryElement2) {
-    this._libraryElement = libraryElement2;
+  void set libraryElement(LibraryElementImpl libraryElement) {
+    this._libraryElement = libraryElement;
     if (_inheritanceManager != null) {
-      _inheritanceManager.libraryElement = libraryElement2;
+      _inheritanceManager.libraryElement = libraryElement;
     }
   }
   String toString() => librarySource.shortName;
@@ -6349,9 +6443,9 @@
    * @param element the class being tested
    * @return `true` if the given element represents a class that has the proxy annotation
    */
-  static bool classHasProxyAnnotation(Element element2) {
-    if (element2 is ClassElement) {
-      ClassElement classElement = element2 as ClassElement;
+  static bool classHasProxyAnnotation(Element element) {
+    if (element is ClassElement) {
+      ClassElement classElement = element as ClassElement;
       List<ElementAnnotation> annotations = classElement.metadata;
       for (ElementAnnotation annotation in annotations) {
         Element elementAnnotation = annotation.element;
@@ -7112,11 +7206,11 @@
    * @param expression the expression being tested
    * @return `true` if the given expression terminates abruptly
    */
-  bool isAbruptTermination(Expression expression2) {
-    while (expression2 is ParenthesizedExpression) {
-      expression2 = ((expression2 as ParenthesizedExpression)).expression;
+  bool isAbruptTermination(Expression expression) {
+    while (expression is ParenthesizedExpression) {
+      expression = ((expression as ParenthesizedExpression)).expression;
     }
-    return expression2 is ThrowExpression || expression2 is RethrowExpression;
+    return expression is ThrowExpression || expression is RethrowExpression;
   }
 
   /**
@@ -7404,6 +7498,16 @@
     }
     return null;
   }
+  Object visitFormalParameterList(FormalParameterList node) {
+    super.visitFormalParameterList(node);
+    if (nameScope is FunctionScope) {
+      ((nameScope as FunctionScope)).defineParameters();
+    }
+    if (nameScope is FunctionTypeScope) {
+      ((nameScope as FunctionTypeScope)).defineParameters();
+    }
+    return null;
+  }
   Object visitForStatement(ForStatement node) {
     Scope outerNameScope = nameScope;
     LabelScope outerLabelScope = labelScope;
@@ -7813,8 +7917,8 @@
    *
    * @param thisType the type representing the class containing the nodes being analyzed
    */
-  void set thisType(InterfaceType thisType2) {
-    this._thisType = thisType2;
+  void set thisType(InterfaceType thisType) {
+    this._thisType = thisType;
   }
 
   /**
@@ -9943,12 +10047,12 @@
     TypeArgumentList argumentList = node.typeArguments;
     Element element = nameScope.lookup(typeName, definingLibrary);
     if (element == null) {
-      if (typeName.name == _dynamicType.name) {
-        setElement(typeName, _dynamicType.element);
+      if (typeName.name == this._dynamicType.name) {
+        setElement(typeName, this._dynamicType.element);
         if (argumentList != null) {
         }
-        typeName.staticType = _dynamicType;
-        node.type = _dynamicType;
+        typeName.staticType = this._dynamicType;
+        node.type = this._dynamicType;
         return null;
       }
       VoidTypeImpl voidType = VoidTypeImpl.instance;
@@ -10024,10 +10128,10 @@
       if (element is MultiplyDefinedElement) {
         setElement(typeName, element);
       } else {
-        setElement(typeName, _dynamicType.element);
+        setElement(typeName, this._dynamicType.element);
       }
-      typeName.staticType = _dynamicType;
-      node.type = _dynamicType;
+      typeName.staticType = this._dynamicType;
+      node.type = this._dynamicType;
       return null;
     }
     Type2 type = null;
@@ -10069,9 +10173,9 @@
           reportError5(StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
         }
       }
-      setElement(typeName, _dynamicType.element);
-      typeName.staticType = _dynamicType;
-      node.type = _dynamicType;
+      setElement(typeName, this._dynamicType.element);
+      typeName.staticType = this._dynamicType;
+      node.type = this._dynamicType;
       return null;
     }
     if (argumentList != null) {
@@ -10093,7 +10197,7 @@
       argumentCount = typeArguments.length;
       if (argumentCount < parameterCount) {
         for (int i = argumentCount; i < parameterCount; i++) {
-          typeArguments.add(_dynamicType);
+          typeArguments.add(this._dynamicType);
         }
       }
       if (type is InterfaceTypeImpl) {
@@ -10513,12 +10617,12 @@
    * @param returnType the (possibly `null`) return type of the function
    * @param parameterList the list of parameters to the function
    */
-  void setFunctionTypedParameterType(ParameterElementImpl element, TypeName returnType2, FormalParameterList parameterList) {
+  void setFunctionTypedParameterType(ParameterElementImpl element, TypeName returnType, FormalParameterList parameterList) {
     List<ParameterElement> parameters = getElements(parameterList);
     FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl(null);
     aliasElement.synthetic = true;
     aliasElement.shareParameters(parameters);
-    aliasElement.returnType = computeReturnType(returnType2);
+    aliasElement.returnType = computeReturnType(returnType);
     FunctionTypeImpl type = new FunctionTypeImpl.con2(aliasElement);
     ClassElement definingClass = element.getAncestor(ClassElement);
     if (definingClass != null) {
@@ -10655,6 +10759,8 @@
  * @coverage dart.engine.resolver
  */
 class FunctionScope extends EnclosedScope {
+  ExecutableElement _functionElement;
+  bool _parametersDefined = false;
 
   /**
    * Initialize a newly created scope enclosed within another scope.
@@ -10663,23 +10769,25 @@
    * @param functionElement the element representing the type represented by this scope
    */
   FunctionScope(Scope enclosingScope, ExecutableElement functionElement) : super(new EnclosedScope(enclosingScope)) {
-    defineParameters(functionElement);
+    this._functionElement = functionElement;
   }
 
   /**
    * Define the parameters for the given function in the scope that encloses this function.
-   *
-   * @param functionElement the element representing the function represented by this scope
    */
-  void defineParameters(ExecutableElement functionElement) {
+  void defineParameters() {
+    if (_parametersDefined) {
+      return;
+    }
+    _parametersDefined = true;
     Scope parameterScope = enclosingScope;
-    if (functionElement.enclosingElement is ExecutableElement) {
-      String name = functionElement.name;
+    if (_functionElement.enclosingElement is ExecutableElement) {
+      String name = _functionElement.name;
       if (name != null && !name.isEmpty) {
-        parameterScope.define(functionElement);
+        parameterScope.define(_functionElement);
       }
     }
-    for (ParameterElement parameter in functionElement.parameters) {
+    for (ParameterElement parameter in _functionElement.parameters) {
       if (!parameter.isInitializingFormal) {
         parameterScope.define(parameter);
       }
@@ -10693,6 +10801,8 @@
  * @coverage dart.engine.resolver
  */
 class FunctionTypeScope extends EnclosedScope {
+  FunctionTypeAliasElement _typeElement;
+  bool _parametersDefined = false;
 
   /**
    * Initialize a newly created scope enclosed within another scope.
@@ -10701,8 +10811,8 @@
    * @param typeElement the element representing the type alias represented by this scope
    */
   FunctionTypeScope(Scope enclosingScope, FunctionTypeAliasElement typeElement) : super(new EnclosedScope(enclosingScope)) {
-    defineTypeParameters(typeElement);
-    defineParameters(typeElement);
+    this._typeElement = typeElement;
+    defineTypeParameters();
   }
 
   /**
@@ -10710,8 +10820,12 @@
    *
    * @param typeElement the element representing the type represented by this scope
    */
-  void defineParameters(FunctionTypeAliasElement typeElement) {
-    for (ParameterElement parameter in typeElement.parameters) {
+  void defineParameters() {
+    if (_parametersDefined) {
+      return;
+    }
+    _parametersDefined = true;
+    for (ParameterElement parameter in _typeElement.parameters) {
       define(parameter);
     }
   }
@@ -10721,9 +10835,9 @@
    *
    * @param typeElement the element representing the type represented by this scope
    */
-  void defineTypeParameters(FunctionTypeAliasElement typeElement) {
+  void defineTypeParameters() {
     Scope typeParameterScope = enclosingScope;
-    for (TypeParameterElement typeParameter in typeElement.typeParameters) {
+    for (TypeParameterElement typeParameter in _typeElement.typeParameters) {
       typeParameterScope.define(typeParameter);
     }
   }
@@ -10884,7 +10998,7 @@
       if (enclosingLibrary != null) {
         libName2 = enclosingLibrary.definingCompilationUnit.displayName;
       }
-      _errorListener.onError(new AnalysisError.con2(source2, identifier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltName, libName1, libName2]));
+      _errorListener.onError(new AnalysisError.con2(source, identifier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltName, libName1, libName2]));
       return foundElement;
     }
     if (foundElement != null) {
@@ -10927,6 +11041,9 @@
       return foundElement;
     } else if (to == 1) {
       return conflictingMembers[0];
+    } else if (to == 0) {
+      AnalysisEngine.instance.logger.logInformation("Multiply defined SDK element: ${foundElement}");
+      return foundElement;
     }
     List<Element> remaining = new List<Element>(to);
     JavaSystem.arraycopy(conflictingMembers, 0, remaining, 0, to);
@@ -10959,7 +11076,7 @@
           offset = accessor.variable.nameOffset;
         }
       }
-      return new AnalysisError.con2(source2, offset, duplicate.displayName.length, CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, [existing.displayName]);
+      return new AnalysisError.con2(source, offset, duplicate.displayName.length, CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, [existing.displayName]);
     }
     return super.getErrorForDuplicate(existing, duplicate);
   }
@@ -11129,9 +11246,9 @@
    * @param definedNames the mapping table to which the names in the given namespace are to be added
    * @param namespace the namespace containing the names to be added to this namespace
    */
-  void addAll2(Map<String, Element> definedNames2, Namespace namespace) {
+  void addAll2(Map<String, Element> definedNames, Namespace namespace) {
     if (namespace != null) {
-      addAll(definedNames2, namespace.definedNames);
+      addAll(definedNames, namespace.definedNames);
     }
   }
 
@@ -11379,7 +11496,7 @@
   AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
     Source source = duplicate.source;
     if (source == null) {
-      source = source2;
+      source = this.source;
     }
     return new AnalysisError.con2(source, duplicate.nameOffset, duplicate.displayName.length, CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]);
   }
@@ -11397,7 +11514,7 @@
    *
    * @return the source object with which errors should be associated
    */
-  Source get source2 => definingLibrary.definingCompilationUnit.source;
+  Source get source => definingLibrary.definingCompilationUnit.source;
 
   /**
    * Return the element with which the given name is associated, or `null` if the name is not
@@ -11602,14 +11719,14 @@
    * @param result the result containing any errors that need to be reported
    * @param errorCode the error code to be used if the result represents an error
    */
-  void reportErrors(EvaluationResultImpl result, ErrorCode errorCode2) {
+  void reportErrors(EvaluationResultImpl result, ErrorCode errorCode) {
     if (result is ErrorResult) {
       for (ErrorResult_ErrorData data in ((result as ErrorResult)).errorData) {
         ErrorCode dataErrorCode = data.errorCode;
         if (identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_INT) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM)) {
           _errorReporter.reportError2(dataErrorCode, data.node, []);
         } else {
-          _errorReporter.reportError2(errorCode2, data.node, []);
+          _errorReporter.reportError2(errorCode, data.node, []);
         }
       }
     }
@@ -11666,11 +11783,11 @@
    *
    * @param parameters the list of parameters to be validated
    */
-  void validateDefaultValues(FormalParameterList parameters2) {
-    if (parameters2 == null) {
+  void validateDefaultValues(FormalParameterList parameters) {
+    if (parameters == null) {
       return;
     }
-    for (FormalParameter parameter in parameters2.parameters) {
+    for (FormalParameter parameter in parameters.parameters) {
       if (parameter is DefaultFormalParameter) {
         DefaultFormalParameter defaultParameter = parameter as DefaultFormalParameter;
         Expression defaultValue = defaultParameter.defaultValue;
@@ -12555,7 +12672,7 @@
    * @see StaticWarningCode#INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE
    * @see StaticWarningCode#INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES
    */
-  bool checkForAllInvalidOverrideErrorCodes(ExecutableElement executableElement, List<ParameterElement> parameters2, List<ASTNode> parameterLocations, SimpleIdentifier errorNameTarget) {
+  bool checkForAllInvalidOverrideErrorCodes(ExecutableElement executableElement, List<ParameterElement> parameters, List<ASTNode> parameterLocations, SimpleIdentifier errorNameTarget) {
     String executableElementName = executableElement.name;
     ExecutableElement overriddenExecutable = _inheritanceManager.lookupInheritance(_enclosingClass, executableElementName);
     bool isGetter = false;
@@ -12675,8 +12792,8 @@
       if (!overriddenNamedPTEntry.getValue().isAssignableTo(overridingType)) {
         ParameterElement parameterToSelect = null;
         ASTNode parameterLocationToSelect = null;
-        for (int i = 0; i < parameters2.length; i++) {
-          ParameterElement parameter = parameters2[i];
+        for (int i = 0; i < parameters.length; i++) {
+          ParameterElement parameter = parameters[i];
           if (identical(parameter.parameterKind, ParameterKind.NAMED) && overriddenNamedPTEntry.getKey() == parameter.name) {
             parameterToSelect = parameter;
             parameterLocationToSelect = parameterLocations[i];
@@ -12697,8 +12814,8 @@
     List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>();
     List<ParameterElementImpl> overriddenParameterElts = new List<ParameterElementImpl>();
     List<ParameterElement> overriddenPEs = overriddenExecutable.parameters;
-    for (int i = 0; i < parameters2.length; i++) {
-      ParameterElement parameter = parameters2[i];
+    for (int i = 0; i < parameters.length; i++) {
+      ParameterElement parameter = parameters[i];
       if (parameter.parameterKind.isOptional) {
         formalParameters.add(parameterLocations[i]);
         parameterElts.add(parameter as ParameterElementImpl);
@@ -13250,11 +13367,11 @@
    * @return `true` if and only if an error code is generated on the passed node
    * @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
    */
-  bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 type2) {
-    if (type2 == null || type2 == _typeProvider.intType || type2 == _typeProvider.stringType) {
+  bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 type) {
+    if (type == null || type == _typeProvider.intType || type == _typeProvider.stringType) {
       return false;
     }
-    Element element = type2.element;
+    Element element = type.element;
     if (element is! ClassElement) {
       return false;
     }
@@ -14258,14 +14375,14 @@
    * @return `true` if and only if an error code is generated on the passed node
    * @see StaticTypeWarningCode#INSTANCE_ACCESS_TO_STATIC_MEMBER
    */
-  bool checkForInstanceAccessToStaticMember(Expression target, SimpleIdentifier name2) {
+  bool checkForInstanceAccessToStaticMember(Expression target, SimpleIdentifier name) {
     if (target == null) {
       return false;
     }
     if (_isInComment) {
       return false;
     }
-    Element element = name2.staticElement;
+    Element element = name.staticElement;
     if (element is! ExecutableElement) {
       return false;
     }
@@ -14279,7 +14396,7 @@
     if (isTypeReference(target)) {
       return false;
     }
-    _errorReporter.reportError2(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, name2, [name2.name]);
+    _errorReporter.reportError2(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, name, [name.name]);
     return true;
   }
 
@@ -15274,8 +15391,8 @@
    * @return `true` if and only if an error code is generated on the passed node
    * @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER
    */
-  bool checkForStaticAccessToInstanceMember(Expression target, SimpleIdentifier name2) {
-    Element element = name2.staticElement;
+  bool checkForStaticAccessToInstanceMember(Expression target, SimpleIdentifier name) {
+    Element element = name.staticElement;
     if (element is! ExecutableElement) {
       return false;
     }
@@ -15286,7 +15403,7 @@
     if (!isTypeReference(target)) {
       return false;
     }
-    _errorReporter.reportError2(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, name2, [name2.name]);
+    _errorReporter.reportError2(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, name, [name.name]);
     return true;
   }
 
@@ -15475,8 +15592,8 @@
    * @return `true` if and only if an error code is generated on the passed node
    * @see StaticTypeWarningCode#UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
    */
-  bool checkForUnqualifiedReferenceToNonLocalStaticMember(SimpleIdentifier name2) {
-    Element element = name2.staticElement;
+  bool checkForUnqualifiedReferenceToNonLocalStaticMember(SimpleIdentifier name) {
+    Element element = name.staticElement;
     if (element == null || element is TypeParameterElement) {
       return false;
     }
@@ -15490,7 +15607,7 @@
     if (identical(enclosingElement, _enclosingClass)) {
       return false;
     }
-    _errorReporter.reportError2(StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, name2, [name2.name]);
+    _errorReporter.reportError2(StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, name, [name.name]);
     return true;
   }
 
diff --git a/pkg/analyzer_experimental/lib/src/generated/scanner.dart b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
index 67ffec0..7ee43be 100644
--- a/pkg/analyzer_experimental/lib/src/generated/scanner.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
@@ -38,13 +38,13 @@
    * @param length the number of strings in the array that pass through the state being built
    * @return the state that was created
    */
-  static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length2) {
+  static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length) {
     List<KeywordState> result = new List<KeywordState>(26);
-    assert(length2 != 0);
+    assert(length != 0);
     int chunk = 0x0;
     int chunkStart = -1;
     bool isLeaf = false;
-    for (int i = offset; i < offset + length2; i++) {
+    for (int i = offset; i < offset + length; i++) {
       if (strings[i].length == start) {
         isLeaf = true;
       }
@@ -61,9 +61,9 @@
     }
     if (chunkStart != -1) {
       assert(result[chunk - 0x61] == null);
-      result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, offset + length2 - chunkStart);
+      result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, offset + length - chunkStart);
     } else {
-      assert(length2 == 1);
+      assert(length == 1);
       return new KeywordState(_EMPTY_TABLE, strings[offset]);
     }
     if (isLeaf) {
@@ -544,12 +544,12 @@
       _lastComment = _lastComment.setNext(new StringToken(type, value, _tokenStart));
     }
   }
-  void appendEndToken(TokenType type2, TokenType beginType) {
+  void appendEndToken(TokenType type, TokenType beginType) {
     Token token;
     if (_firstComment == null) {
-      token = new Token(type2, _tokenStart);
+      token = new Token(type, _tokenStart);
     } else {
-      token = new TokenWithComment(type2, _tokenStart, _firstComment);
+      token = new TokenWithComment(type, _tokenStart, _firstComment);
       _firstComment = null;
       _lastComment = null;
     }
@@ -643,8 +643,8 @@
       return advance();
     }
     if (next == 0x72) {
-      int peek2 = peek();
-      if (peek2 == 0x22 || peek2 == 0x27) {
+      int peek = this.peek();
+      if (peek == 0x22 || peek == 0x27) {
         int start = offset;
         return tokenizeString(advance(), start, true);
       }
@@ -1017,23 +1017,23 @@
     beginToken();
     return next;
   }
-  int tokenizeKeywordOrIdentifier(int next2, bool allowDollar) {
+  int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
     KeywordState state = KeywordState.KEYWORD_STATE;
     int start = offset;
-    while (state != null && 0x61 <= next2 && next2 <= 0x7A) {
-      state = state.next(next2 as int);
-      next2 = advance();
+    while (state != null && 0x61 <= next && next <= 0x7A) {
+      state = state.next(next as int);
+      next = advance();
     }
     if (state == null || state.keyword() == null) {
-      return tokenizeIdentifier(next2, start, allowDollar);
+      return tokenizeIdentifier(next, start, allowDollar);
     }
-    if ((0x41 <= next2 && next2 <= 0x5A) || (0x30 <= next2 && next2 <= 0x39) || next2 == 0x5F || next2 == 0x24) {
-      return tokenizeIdentifier(next2, start, allowDollar);
-    } else if (next2 < 128) {
+    if ((0x41 <= next && next <= 0x5A) || (0x30 <= next && next <= 0x39) || next == 0x5F || next == 0x24) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    } else if (next < 128) {
       appendKeywordToken(state.keyword());
-      return next2;
+      return next;
     } else {
-      return tokenizeIdentifier(next2, start, allowDollar);
+      return tokenizeIdentifier(next, start, allowDollar);
     }
   }
   int tokenizeLessThan(int next) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk.dart b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
index 2accc54..234742f 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
@@ -157,8 +157,8 @@
    *
    * @param category the name of the category containing the library
    */
-  void set category(String category2) {
-    this._category = category2;
+  void set category(String category) {
+    this._category = category;
   }
 
   /**
@@ -173,8 +173,8 @@
    *
    * @param documented `true` if the library is documented
    */
-  void set documented(bool documented2) {
-    this._documented = documented2;
+  void set documented(bool documented) {
+    this._documented = documented;
   }
 
   /**
@@ -182,8 +182,8 @@
    *
    * @param implementation `true` if the library is an implementation library
    */
-  void set implementation(bool implementation2) {
-    this._implementation = implementation2;
+  void set implementation(bool implementation) {
+    this._implementation = implementation;
   }
 
   /**
@@ -192,8 +192,8 @@
    *
    * @param path the path to the file defining the library
    */
-  void set path(String path2) {
-    this._path = path2;
+  void set path(String path) {
+    this._path = path;
   }
 
   /**
diff --git a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
index 032d5e7..6d3d7e9 100644
--- a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
@@ -195,7 +195,9 @@
       advance();
 
     }
-    if (!isEOF(token2)) {
+    // TODO(pquitslund): consider a better way to notice trailing synthetics
+    if (!isEOF(token2) && 
+        !(isCLOSE_CURLY_BRACKET(token2) && isEOF(token2.next))) {
       throw new FormatterException(
           'Expected "EOF" but got "${token2}".');
     }
@@ -261,6 +263,11 @@
         return true;
       }
     }
+    // Advance past synthetic { } tokens
+    if (isOPEN_CURLY_BRACKET(token2) || isCLOSE_CURLY_BRACKET(token2)) {
+      token2 = token2.next;
+      return checkTokens();
+    }
 
     return false;
   }
@@ -286,6 +293,14 @@
 /// Test if this token is an INDEX token.
 bool isINDEX(Token token) => tokenIs(token, TokenType.INDEX);
 
+/// Test if this token is a OPEN_CURLY_BRACKET token.
+bool isOPEN_CURLY_BRACKET(Token token) =>
+    tokenIs(token, TokenType.OPEN_CURLY_BRACKET);
+
+/// Test if this token is a CLOSE_CURLY_BRACKET token.
+bool isCLOSE_CURLY_BRACKET(Token token) =>
+    tokenIs(token, TokenType.CLOSE_CURLY_BRACKET);
+
 /// Test if this token is a OPEN_SQUARE_BRACKET token.
 bool isOPEN_SQ_BRACKET(Token token) =>
     tokenIs(token, TokenType.OPEN_SQUARE_BRACKET);
@@ -294,8 +309,19 @@
 bool isCLOSE_SQUARE_BRACKET(Token token) =>
     tokenIs(token, TokenType.CLOSE_SQUARE_BRACKET);
 
+
 /// An AST visitor that drives formatting heuristics.
 class SourceVisitor implements ASTVisitor {
+  
+  static final OPEN_CURLY = syntheticToken(TokenType.OPEN_CURLY_BRACKET, '{');
+  static final CLOSE_CURLY = syntheticToken(TokenType.CLOSE_CURLY_BRACKET, '}');
+  
+  static const SYNTH_OFFSET = -13;
+  
+  static StringToken syntheticToken(TokenType type, String value) =>
+      new StringToken(type, value, SYNTH_OFFSET);
+  
+  static bool isSynthetic(Token token) => token.offset == SYNTH_OFFSET;
 
   /// The writer to which the source is to be written.
   final SourceWriter writer;
@@ -308,6 +334,9 @@
 
   /// A flag to indicate that a newline should be emitted before the next token.
   bool needsNewline = false;
+  
+  /// A counter for spaces that should be emitted preceding the next token.
+  int leadingSpaces = 0;
 
   /// Used for matching EOL comments
   final twoSlashes = new RegExp(r'//[^/]');
@@ -514,13 +543,41 @@
     token(node.period);
     visit(node.name);
     visit(node.parameters);
-    token(node.separator /* = or : */, precededBy: space, followedBy: space);
-    visitNodes(node.initializers, separatedBy: commaSeperator);
-    visit(node.redirectedConstructor);
+    
+    // Check for redirects or initializer lists
+    if (node.separator != null) {
+      if (node.redirectedConstructor != null) {
+        visitConstructorRedirects(node);
+      } else { 
+        visitConstructorInitializers(node);
+      }
+    }
 
     visitPrefixedBody(space, node.body);
   }
 
+  visitConstructorInitializers(ConstructorDeclaration node) {
+    newlines();
+    indent(2);
+    token(node.separator /* : */);
+    space();
+    for (var i = 0; i < node.initializers.length; i++) {
+      if (i > 0) {
+        comma();
+        newlines();
+        space(2);
+      }
+      node.initializers[i].accept(this);
+    } 
+    unindent(2);
+  }
+
+  visitConstructorRedirects(ConstructorDeclaration node) {
+    token(node.separator /* = */, precededBy: space, followedBy: space);
+    visitNodes(node.initializers, separatedBy: commaSeperator);
+    visit(node.redirectedConstructor);
+  }
+  
   visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
     token(node.keyword);
     token(node.period);
@@ -730,24 +787,26 @@
     space();
     visitNodes(node.hiddenNames, separatedBy: commaSeperator);
   }
-
+  
   visitIfStatement(IfStatement node) {
+    var hasElse = node.elseStatement != null;
     token(node.ifKeyword);
     space();
     token(node.leftParenthesis);
     visit(node.condition);
     token(node.rightParenthesis);
     space();
-    visit(node.thenStatement);
-    //visitPrefixed(' else ', node.elseStatement);
-    if (node.elseStatement != null) {
+    if (hasElse) {
+      printAsBlock(node.thenStatement);
       space();
       token(node.elseKeyword);
       space();
-      visit(node.elseStatement);
+      printAsBlock(node.elseStatement);
+    } else {
+      visit(node.thenStatement);
     }
   }
-
+  
   visitImplementsClause(ImplementsClause node) {
     token(node.keyword);
     space();
@@ -1226,6 +1285,13 @@
     }
   }
   
+  emitSpaces() {
+    while (leadingSpaces > 0) {
+      writer.print(' ');
+      leadingSpaces--;
+    }
+  }
+  
   checkForSelectionUpdate(Token token) {
     // Cache the first token on or AFTER the selection offset
     if (preSelection != null && selection == null) {
@@ -1233,7 +1299,8 @@
       var overshot = token.offset - preSelection.offset;
       if (overshot >= 0) {
         //TODO(pquitslund): update length (may need truncating)
-        selection = new Selection(writer.toString().length - overshot, 
+        selection = new Selection(
+            writer.toString().length + leadingSpaces - overshot, 
             preSelection.length);
       }
     }
@@ -1245,15 +1312,16 @@
   }
 
   comma() {
-    append(',');
+    writer.print(',');
   }
 
+  
   /// Emit a non-breakable space.
-  space() {
+  space([n = 1]) {
     //TODO(pquitslund): replace with a proper space token
-    append(' ');
+    leadingSpaces+=n;
   }
-
+  
   /// Emit a breakable space
   breakableSpace() {
     //Implement
@@ -1262,21 +1330,40 @@
   /// Append the given [string] to the source writer if it's non-null.
   append(String string) {
     if (string != null && !string.isEmpty) {
+      emitSpaces();
       writer.print(string);
     }
   }
 
   /// Indent.
-  indent() {
-    writer.indent();
+  indent([n = 1]) {
+    while (n-- > 0) {
+      writer.indent();
+    }
   }
-
+  
   /// Unindent
-  unindent() {
-    writer.unindent();
+  unindent([n = 1]) {
+    while (n-- > 0) {
+      writer.unindent();
+    }
   }
-
-
+  
+  /// Print this statement as if it were a block (e.g., surrounded by braces).
+  printAsBlock(Statement statement) {
+    if (statement is! Block) {
+      token(OPEN_CURLY);
+      indent();
+      newlines();
+      visit(statement);
+      newlines();
+      unindent();
+      token(CLOSE_CURLY);
+    } else {
+      visit(statement);
+    }
+  }
+  
   /// Emit any detected comments and newlines or a minimum as specified
   /// by [min].
   int emitPrecedingCommentsAndNewlines(Token token, {min: 0}) {
@@ -1294,7 +1381,7 @@
     var lines = max(min, countNewlinesBetween(previousToken, currentToken));
     writer.newlines(lines);
 
-    var previousToken = currentToken.previous;
+    previousToken = currentToken.previous;
 
     while (comment != null) {
 
@@ -1306,7 +1393,7 @@
         writer.newlines(newlines);
         lines += newlines;
       } else if (!isEOF(token)) {
-        space();
+        append(' ');
       }
 
       previousToken = comment;
@@ -1336,7 +1423,7 @@
       var ws = countSpacesBetween(previousToken, comment);
       // Preserve one space but no more
       if (ws > 0) {
-        space();
+        append(' ');
       }
     }
 
@@ -1361,7 +1448,7 @@
 
   /// Count the blanks between these two tokens.
   int countNewlinesBetween(Token last, Token current) {
-    if (last == null || current == null) {
+    if (last == null || current == null || isSynthetic(last)) {
       return 0;
     }
 
diff --git a/pkg/analyzer_experimental/test/generated/ast_test.dart b/pkg/analyzer_experimental/test/generated/ast_test.dart
index 36380ec..0c07d4c 100644
--- a/pkg/analyzer_experimental/test/generated/ast_test.dart
+++ b/pkg/analyzer_experimental/test/generated/ast_test.dart
@@ -262,7 +262,7 @@
   static CompilationUnit compilationUnit5(String scriptTag) => compilationUnit8(scriptTag, null, null);
   static CompilationUnit compilationUnit6(String scriptTag, List<CompilationUnitMember> declarations) => compilationUnit8(scriptTag, null, list(declarations));
   static CompilationUnit compilationUnit7(String scriptTag, List<Directive> directives) => compilationUnit8(scriptTag, list(directives), null);
-  static CompilationUnit compilationUnit8(String scriptTag2, List<Directive> directives, List<CompilationUnitMember> declarations) => new CompilationUnit.full(TokenFactory.token3(TokenType.EOF), scriptTag2 == null ? null : scriptTag(scriptTag2), directives == null ? new List<Directive>() : directives, declarations == null ? new List<CompilationUnitMember>() : declarations, TokenFactory.token3(TokenType.EOF));
+  static CompilationUnit compilationUnit8(String scriptTag, List<Directive> directives, List<CompilationUnitMember> declarations) => new CompilationUnit.full(TokenFactory.token3(TokenType.EOF), scriptTag == null ? null : ASTFactory.scriptTag(scriptTag), directives == null ? new List<Directive>() : directives, declarations == null ? new List<CompilationUnitMember>() : declarations, TokenFactory.token3(TokenType.EOF));
   static ConditionalExpression conditionalExpression(Expression condition, Expression thenExpression, Expression elseExpression) => new ConditionalExpression.full(condition, TokenFactory.token3(TokenType.QUESTION), thenExpression, TokenFactory.token3(TokenType.COLON), elseExpression);
   static ConstructorDeclaration constructorDeclaration(Identifier returnType, String name, FormalParameterList parameters, List<ConstructorInitializer> initializers) => new ConstructorDeclaration.full(null, null, TokenFactory.token(Keyword.EXTERNAL), null, null, returnType, name == null ? null : TokenFactory.token3(TokenType.PERIOD), name == null ? null : identifier3(name), parameters, initializers == null || initializers.isEmpty ? null : TokenFactory.token3(TokenType.PERIOD), initializers == null ? new List<ConstructorInitializer>() : initializers, null, emptyFunctionBody());
   static ConstructorDeclaration constructorDeclaration2(Keyword constKeyword, Keyword factoryKeyword, Identifier returnType, String name, FormalParameterList parameters, List<ConstructorInitializer> initializers, FunctionBody body) => new ConstructorDeclaration.full(null, null, null, constKeyword == null ? null : TokenFactory.token(constKeyword), factoryKeyword == null ? null : TokenFactory.token(factoryKeyword), returnType, name == null ? null : TokenFactory.token3(TokenType.PERIOD), name == null ? null : identifier3(name), parameters, initializers == null || initializers.isEmpty ? null : TokenFactory.token3(TokenType.PERIOD), initializers == null ? new List<ConstructorInitializer>() : initializers, null, body);
@@ -306,7 +306,7 @@
     }
     return new HideCombinator.full(TokenFactory.token2("hide"), identifierList);
   }
-  static PrefixedIdentifier identifier(SimpleIdentifier prefix, SimpleIdentifier identifier2) => new PrefixedIdentifier.full(prefix, TokenFactory.token3(TokenType.PERIOD), identifier2);
+  static PrefixedIdentifier identifier(SimpleIdentifier prefix, SimpleIdentifier identifier) => new PrefixedIdentifier.full(prefix, TokenFactory.token3(TokenType.PERIOD), identifier);
   static SimpleIdentifier identifier3(String lexeme) => new SimpleIdentifier.full(TokenFactory.token4(TokenType.IDENTIFIER, lexeme));
   static PrefixedIdentifier identifier4(String prefix, SimpleIdentifier identifier) => new PrefixedIdentifier.full(identifier3(prefix), TokenFactory.token3(TokenType.PERIOD), identifier);
   static PrefixedIdentifier identifier5(String prefix, String identifier) => new PrefixedIdentifier.full(identifier3(prefix), TokenFactory.token3(TokenType.PERIOD), identifier3(identifier));
@@ -324,8 +324,8 @@
   static InterpolationExpression interpolationExpression2(String identifier) => new InterpolationExpression.full(TokenFactory.token3(TokenType.STRING_INTERPOLATION_IDENTIFIER), identifier3(identifier), null);
   static InterpolationString interpolationString(String contents, String value) => new InterpolationString.full(TokenFactory.token2(contents), value);
   static IsExpression isExpression(Expression expression, bool negated, TypeName type) => new IsExpression.full(expression, TokenFactory.token(Keyword.IS), negated ? TokenFactory.token3(TokenType.BANG) : null, type);
-  static Label label(SimpleIdentifier label2) => new Label.full(label2, TokenFactory.token3(TokenType.COLON));
-  static Label label2(String label22) => label(identifier3(label22));
+  static Label label(SimpleIdentifier label) => new Label.full(label, TokenFactory.token3(TokenType.COLON));
+  static Label label2(String label) => ASTFactory.label(identifier3(label));
   static LabeledStatement labeledStatement(List<Label> labels, Statement statement) => new LabeledStatement.full(labels, statement);
   static LibraryDirective libraryDirective(List<Annotation> metadata, LibraryIdentifier libraryName) => new LibraryDirective.full(null, metadata, TokenFactory.token(Keyword.LIBRARY), libraryName, TokenFactory.token3(TokenType.SEMICOLON));
   static LibraryDirective libraryDirective2(String libraryName) => libraryDirective(new List<Annotation>(), libraryIdentifier2([libraryName]));
@@ -374,7 +374,7 @@
   static RethrowExpression rethrowExpression() => new RethrowExpression.full(TokenFactory.token(Keyword.RETHROW));
   static ReturnStatement returnStatement() => returnStatement2(null);
   static ReturnStatement returnStatement2(Expression expression) => new ReturnStatement.full(TokenFactory.token(Keyword.RETURN), expression, TokenFactory.token3(TokenType.SEMICOLON));
-  static ScriptTag scriptTag(String scriptTag2) => new ScriptTag.full(TokenFactory.token2(scriptTag2));
+  static ScriptTag scriptTag(String scriptTag) => new ScriptTag.full(TokenFactory.token2(scriptTag));
   static ShowCombinator showCombinator(List<SimpleIdentifier> identifiers) => new ShowCombinator.full(TokenFactory.token2("show"), list(identifiers));
   static ShowCombinator showCombinator2(List<String> identifiers) {
     List<SimpleIdentifier> identifierList = new List<SimpleIdentifier>();
@@ -1420,7 +1420,7 @@
     assertSource("library l;", ASTFactory.compilationUnit3([ASTFactory.libraryDirective2("l")]));
   }
   void test_visitCompilationUnit_directive_declaration() {
-    assertSource("library l; var a;", ASTFactory.compilationUnit4(ASTFactory.list([(ASTFactory.libraryDirective2("l") as Directive)]), ASTFactory.list([(ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember)])));
+    assertSource("library l; var a;", ASTFactory.compilationUnit4(ASTFactory.list([ASTFactory.libraryDirective2("l") as Directive]), ASTFactory.list([ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember])));
   }
   void test_visitCompilationUnit_empty() {
     assertSource("", ASTFactory.compilationUnit());
@@ -1435,7 +1435,7 @@
     assertSource("!#/bin/dartvm library l;", ASTFactory.compilationUnit7("!#/bin/dartvm", [ASTFactory.libraryDirective2("l")]));
   }
   void test_visitCompilationUnit_script_directives_declarations() {
-    assertSource("!#/bin/dartvm library l; var a;", ASTFactory.compilationUnit8("!#/bin/dartvm", ASTFactory.list([(ASTFactory.libraryDirective2("l") as Directive)]), ASTFactory.list([(ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember)])));
+    assertSource("!#/bin/dartvm library l; var a;", ASTFactory.compilationUnit8("!#/bin/dartvm", ASTFactory.list([ASTFactory.libraryDirective2("l") as Directive]), ASTFactory.list([ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember])));
   }
   void test_visitConditionalExpression() {
     assertSource("a ? b : c", ASTFactory.conditionalExpression(ASTFactory.identifier3("a"), ASTFactory.identifier3("b"), ASTFactory.identifier3("c")));
@@ -1451,7 +1451,7 @@
   }
   void test_visitConstructorDeclaration_multipleInitializers() {
     assertSource("C() : a = b, c = d {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), null, ASTFactory.formalParameterList([]), ASTFactory.list([
-        (ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer),
+        ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer,
         ASTFactory.constructorFieldInitializer(false, "c", ASTFactory.identifier3("d"))]), ASTFactory.blockFunctionBody2([])));
   }
   void test_visitConstructorDeclaration_multipleParameters() {
@@ -1463,7 +1463,7 @@
     assertSource("C.m() {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), "m", ASTFactory.formalParameterList([]), null, ASTFactory.blockFunctionBody2([])));
   }
   void test_visitConstructorDeclaration_singleInitializer() {
-    assertSource("C() : a = b {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), null, ASTFactory.formalParameterList([]), ASTFactory.list([(ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer)]), ASTFactory.blockFunctionBody2([])));
+    assertSource("C() : a = b {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), null, ASTFactory.formalParameterList([]), ASTFactory.list([ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer]), ASTFactory.blockFunctionBody2([])));
   }
   void test_visitConstructorFieldInitializer_withoutThis() {
     assertSource("a = b", ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")));
@@ -1511,7 +1511,7 @@
     assertSource(";", ASTFactory.emptyStatement());
   }
   void test_visitExportDirective_combinator() {
-    assertSource("export 'a.dart' show A;", ASTFactory.exportDirective2("a.dart", [(ASTFactory.showCombinator([ASTFactory.identifier3("A")]) as Combinator)]));
+    assertSource("export 'a.dart' show A;", ASTFactory.exportDirective2("a.dart", [ASTFactory.showCombinator([ASTFactory.identifier3("A")]) as Combinator]));
   }
   void test_visitExportDirective_combinators() {
     assertSource("export 'a.dart' show A hide B;", ASTFactory.exportDirective2("a.dart", [
@@ -1630,7 +1630,7 @@
     assertSource("for (; c;) {}", ASTFactory.forStatement(null as Expression, ASTFactory.identifier3("c"), null, ASTFactory.block([])));
   }
   void test_visitForStatement_cu() {
-    assertSource("for (; c; u) {}", ASTFactory.forStatement(null as Expression, ASTFactory.identifier3("c"), ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([])));
+    assertSource("for (; c; u) {}", ASTFactory.forStatement(null as Expression, ASTFactory.identifier3("c"), ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([])));
   }
   void test_visitForStatement_e() {
     assertSource("for (e;;) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), null, null, ASTFactory.block([])));
@@ -1639,10 +1639,10 @@
     assertSource("for (e; c;) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), ASTFactory.identifier3("c"), null, ASTFactory.block([])));
   }
   void test_visitForStatement_ecu() {
-    assertSource("for (e; c; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), ASTFactory.identifier3("c"), ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([])));
+    assertSource("for (e; c; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), ASTFactory.identifier3("c"), ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([])));
   }
   void test_visitForStatement_eu() {
-    assertSource("for (e;; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), null, ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([])));
+    assertSource("for (e;; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), null, ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([])));
   }
   void test_visitForStatement_i() {
     assertSource("for (var i;;) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), null, null, ASTFactory.block([])));
@@ -1651,13 +1651,13 @@
     assertSource("for (var i; c;) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), ASTFactory.identifier3("c"), null, ASTFactory.block([])));
   }
   void test_visitForStatement_icu() {
-    assertSource("for (var i; c; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), ASTFactory.identifier3("c"), ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([])));
+    assertSource("for (var i; c; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), ASTFactory.identifier3("c"), ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([])));
   }
   void test_visitForStatement_iu() {
-    assertSource("for (var i;; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), null, ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([])));
+    assertSource("for (var i;; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), null, ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([])));
   }
   void test_visitForStatement_u() {
-    assertSource("for (;; u) {}", ASTFactory.forStatement(null as Expression, null, ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([])));
+    assertSource("for (;; u) {}", ASTFactory.forStatement(null as Expression, null, ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([])));
   }
   void test_visitFunctionDeclaration_getter() {
     assertSource("get f() {}", ASTFactory.functionDeclaration(null, Keyword.GET, "f", ASTFactory.functionExpression()));
diff --git a/pkg/analyzer_experimental/test/generated/element_test.dart b/pkg/analyzer_experimental/test/generated/element_test.dart
index d2571ca..954592e 100644
--- a/pkg/analyzer_experimental/test/generated/element_test.dart
+++ b/pkg/analyzer_experimental/test/generated/element_test.dart
@@ -1716,24 +1716,24 @@
     constructor.type = constructorType;
     return constructor;
   }
-  static ExportElementImpl exportFor(LibraryElement exportedLibrary2, List<NamespaceCombinator> combinators2) {
+  static ExportElementImpl exportFor(LibraryElement exportedLibrary, List<NamespaceCombinator> combinators) {
     ExportElementImpl spec = new ExportElementImpl();
-    spec.exportedLibrary = exportedLibrary2;
-    spec.combinators = combinators2;
+    spec.exportedLibrary = exportedLibrary;
+    spec.combinators = combinators;
     return spec;
   }
-  static FieldElementImpl fieldElement(String name, bool isStatic, bool isFinal, bool isConst, Type2 type2) {
+  static FieldElementImpl fieldElement(String name, bool isStatic, bool isFinal, bool isConst, Type2 type) {
     FieldElementImpl field = new FieldElementImpl.con1(ASTFactory.identifier3(name));
     field.const3 = isConst;
     field.final2 = isFinal;
     field.static = isStatic;
-    field.type = type2;
+    field.type = type;
     PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(field);
     getter.getter = true;
     getter.static = isStatic;
     getter.synthetic = true;
     getter.variable = field;
-    getter.returnType = type2;
+    getter.returnType = type;
     field.getter = getter;
     FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
     getter.type = getterType;
@@ -1743,7 +1743,7 @@
       setter.static = isStatic;
       setter.synthetic = true;
       setter.variable = field;
-      setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type2)];
+      setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type)];
       setter.returnType = VoidTypeImpl.instance;
       setter.type = new FunctionTypeImpl.con1(setter);
       field.setter = setter;
@@ -1822,26 +1822,26 @@
     }
     return _objectElement;
   }
-  static PropertyAccessorElementImpl getterElement(String name, bool isStatic, Type2 type2) {
+  static PropertyAccessorElementImpl getterElement(String name, bool isStatic, Type2 type) {
     FieldElementImpl field = new FieldElementImpl.con1(ASTFactory.identifier3(name));
     field.static = isStatic;
     field.synthetic = true;
-    field.type = type2;
+    field.type = type;
     PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(field);
     getter.getter = true;
     getter.static = isStatic;
     getter.variable = field;
-    getter.returnType = type2;
+    getter.returnType = type;
     field.getter = getter;
     FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
     getter.type = getterType;
     return getter;
   }
-  static ImportElementImpl importFor(LibraryElement importedLibrary2, PrefixElement prefix2, List<NamespaceCombinator> combinators2) {
+  static ImportElementImpl importFor(LibraryElement importedLibrary, PrefixElement prefix, List<NamespaceCombinator> combinators) {
     ImportElementImpl spec = new ImportElementImpl();
-    spec.importedLibrary = importedLibrary2;
-    spec.prefix = prefix2;
-    spec.combinators = combinators2;
+    spec.importedLibrary = importedLibrary;
+    spec.prefix = prefix;
+    spec.combinators = combinators;
     return spec;
   }
   static LibraryElementImpl library(AnalysisContext context, String libraryName) {
@@ -1855,7 +1855,7 @@
   }
   static LocalVariableElementImpl localVariableElement(Identifier name) => new LocalVariableElementImpl(name);
   static LocalVariableElementImpl localVariableElement2(String name) => new LocalVariableElementImpl(ASTFactory.identifier3(name));
-  static MethodElementImpl methodElement(String methodName, Type2 returnType2, List<Type2> argumentTypes) {
+  static MethodElementImpl methodElement(String methodName, Type2 returnType, List<Type2> argumentTypes) {
     MethodElementImpl method = new MethodElementImpl.con1(ASTFactory.identifier3(methodName));
     int count = argumentTypes.length;
     List<ParameterElement> parameters = new List<ParameterElement>(count);
@@ -1866,7 +1866,7 @@
       parameters[i] = parameter;
     }
     method.parameters = parameters;
-    method.returnType = returnType2;
+    method.returnType = returnType;
     FunctionTypeImpl methodType = new FunctionTypeImpl.con1(method);
     method.type = methodType;
     return method;
@@ -1876,10 +1876,10 @@
     parameter.parameterKind = ParameterKind.NAMED;
     return parameter;
   }
-  static ParameterElementImpl namedParameter2(String name, Type2 type2) {
+  static ParameterElementImpl namedParameter2(String name, Type2 type) {
     ParameterElementImpl parameter = new ParameterElementImpl.con1(ASTFactory.identifier3(name));
     parameter.parameterKind = ParameterKind.NAMED;
-    parameter.type = type2;
+    parameter.type = type;
     return parameter;
   }
   static ParameterElementImpl positionalParameter(String name) {
@@ -1887,10 +1887,10 @@
     parameter.parameterKind = ParameterKind.POSITIONAL;
     return parameter;
   }
-  static ParameterElementImpl positionalParameter2(String name, Type2 type2) {
+  static ParameterElementImpl positionalParameter2(String name, Type2 type) {
     ParameterElementImpl parameter = new ParameterElementImpl.con1(ASTFactory.identifier3(name));
     parameter.parameterKind = ParameterKind.POSITIONAL;
-    parameter.type = type2;
+    parameter.type = type;
     return parameter;
   }
   static PrefixElementImpl prefix(String name) => new PrefixElementImpl(ASTFactory.identifier3(name));
@@ -1899,26 +1899,26 @@
     parameter.parameterKind = ParameterKind.REQUIRED;
     return parameter;
   }
-  static ParameterElementImpl requiredParameter2(String name, Type2 type2) {
+  static ParameterElementImpl requiredParameter2(String name, Type2 type) {
     ParameterElementImpl parameter = new ParameterElementImpl.con1(ASTFactory.identifier3(name));
     parameter.parameterKind = ParameterKind.REQUIRED;
-    parameter.type = type2;
+    parameter.type = type;
     return parameter;
   }
-  static PropertyAccessorElementImpl setterElement(String name, bool isStatic, Type2 type2) {
+  static PropertyAccessorElementImpl setterElement(String name, bool isStatic, Type2 type) {
     FieldElementImpl field = new FieldElementImpl.con1(ASTFactory.identifier3(name));
     field.static = isStatic;
     field.synthetic = true;
-    field.type = type2;
+    field.type = type;
     PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(field);
     getter.getter = true;
     getter.static = isStatic;
     getter.variable = field;
-    getter.returnType = type2;
+    getter.returnType = type;
     field.getter = getter;
     FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
     getter.type = getterType;
-    ParameterElementImpl parameter = requiredParameter2("a", type2);
+    ParameterElementImpl parameter = requiredParameter2("a", type);
     PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(field);
     setter.setter = true;
     setter.static = isStatic;
@@ -1932,7 +1932,7 @@
   }
   static TopLevelVariableElementImpl topLevelVariableElement(Identifier name) => new TopLevelVariableElementImpl.con1(name);
   static TopLevelVariableElementImpl topLevelVariableElement2(String name) => new TopLevelVariableElementImpl.con2(name);
-  static TopLevelVariableElementImpl topLevelVariableElement3(String name, bool isFinal, Type2 type2) {
+  static TopLevelVariableElementImpl topLevelVariableElement3(String name, bool isFinal, Type2 type) {
     TopLevelVariableElementImpl variable = new TopLevelVariableElementImpl.con2(name);
     variable.final2 = isFinal;
     PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(variable);
@@ -1940,7 +1940,7 @@
     getter.static = true;
     getter.synthetic = true;
     getter.variable = variable;
-    getter.returnType = type2;
+    getter.returnType = type;
     variable.getter = getter;
     FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
     getter.type = getterType;
@@ -1950,7 +1950,7 @@
       setter.static = true;
       setter.synthetic = true;
       setter.variable = variable;
-      setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type2)];
+      setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type)];
       setter.returnType = VoidTypeImpl.instance;
       setter.type = new FunctionTypeImpl.con1(setter);
       variable.setter = setter;
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart
index 0e21d4b..6229a06 100644
--- a/pkg/analyzer_experimental/test/generated/resolver_test.dart
+++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -1290,6 +1290,16 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_constructorDeclaration_scope_signature() {
+    Source source = addSource(EngineTestCase.createSource([
+        "const app = 0;",
+        "class A {",
+        "  A(@app int app) {}",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_constWithNonConstantArgument_literals() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -1533,6 +1543,30 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_functionDeclaration_scope_returnType() {
+    Source source = addSource(EngineTestCase.createSource(["int f(int) {}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+  void test_functionDeclaration_scope_signature() {
+    Source source = addSource(EngineTestCase.createSource(["const app = 0;", "f(@app int app) {}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+  void test_functionTypeAlias_scope_returnType() {
+    Source source = addSource(EngineTestCase.createSource(["typedef int f(int);"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+  void test_functionTypeAlias_scope_signature() {
+    Source source = addSource(EngineTestCase.createSource(["const app = 0;", "typedef int f(@app int app);"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_implicitThisReferenceInInitializer_constructorName() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -1684,6 +1718,21 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_importPrefixes_withFirstLetterDifference() {
+    Source source = addSource(EngineTestCase.createSource([
+        "library L;",
+        "import 'lib1.dart' as math;",
+        "import 'lib2.dart' as path;",
+        "main() {",
+        "  math.test1();",
+        "  path.test2();",
+        "}"]));
+    addSource2("/lib1.dart", EngineTestCase.createSource(["library lib1;", "test1() {}"]));
+    addSource2("/lib2.dart", EngineTestCase.createSource(["library lib2;", "test2() {}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_inconsistentCaseExpressionTypes() {
     Source source = addSource(EngineTestCase.createSource([
         "f(var p) {",
@@ -2204,6 +2253,16 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_methodDeclaration_scope_signature() {
+    Source source = addSource(EngineTestCase.createSource([
+        "const app = 0;",
+        "class A {",
+        "  foo(@app int app) {}",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_misMatchedGetterAndSetterTypes_instance_sameTypes() {
     Source source = addSource(EngineTestCase.createSource([
         "class C {",
@@ -3452,6 +3511,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_constWithUndefinedConstructorDefault);
       });
+      _ut.test('test_constructorDeclaration_scope_signature', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_constructorDeclaration_scope_signature);
+      });
       _ut.test('test_defaultValueInFunctionTypeAlias', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_defaultValueInFunctionTypeAlias);
@@ -3560,6 +3623,22 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_finalNotInitialized_redirectingConstructor);
       });
+      _ut.test('test_functionDeclaration_scope_returnType', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_functionDeclaration_scope_returnType);
+      });
+      _ut.test('test_functionDeclaration_scope_signature', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_functionDeclaration_scope_signature);
+      });
+      _ut.test('test_functionTypeAlias_scope_returnType', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_functionTypeAlias_scope_returnType);
+      });
+      _ut.test('test_functionTypeAlias_scope_signature', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_functionTypeAlias_scope_signature);
+      });
       _ut.test('test_implicitThisReferenceInInitializer_constructorName', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_implicitThisReferenceInInitializer_constructorName);
@@ -3616,6 +3695,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_importOfNonLibrary_libraryNotDeclared);
       });
+      _ut.test('test_importPrefixes_withFirstLetterDifference', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_importPrefixes_withFirstLetterDifference);
+      });
       _ut.test('test_inconsistentCaseExpressionTypes', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_inconsistentCaseExpressionTypes);
@@ -3812,6 +3895,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_memberWithClassName_setter);
       });
+      _ut.test('test_methodDeclaration_scope_signature', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_methodDeclaration_scope_signature);
+      });
       _ut.test('test_misMatchedGetterAndSetterTypes_instance_sameTypes', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_misMatchedGetterAndSetterTypes_instance_sameTypes);
@@ -4906,6 +4993,18 @@
     resolve(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
+  void test_undefinedMethod_assignmentExpression() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B {",
+        "  f(A a) {",
+        "    A a2 = new A();",
+        "    a += a2;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
+  }
   void test_undefinedMethod_ignoreTypePropagation() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {}",
@@ -4913,7 +5012,7 @@
         "  m() {}",
         "}",
         "class C {",
-        "f() {",
+        "  f() {",
         "    A a = new B();",
         "    a.m();",
         "  }",
@@ -4943,6 +5042,16 @@
     resolve(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
+  void test_undefinedOperator_postfixExpression() {
+    Source source = addSource(EngineTestCase.createSource(["class A {}", "f(A a) {", "  a++;", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+  void test_undefinedOperator_prefixExpression() {
+    Source source = addSource(EngineTestCase.createSource(["class A {}", "f(A a) {", "  ++a;", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
   void test_undefinedSetter() {
     Source source = addSource(EngineTestCase.createSource(["class T {}", "f(T e1) { e1.m = 0; }"]));
     resolve(source);
@@ -5280,6 +5389,10 @@
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedMethod);
       });
+      _ut.test('test_undefinedMethod_assignmentExpression', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_undefinedMethod_assignmentExpression);
+      });
       _ut.test('test_undefinedMethod_ignoreTypePropagation', () {
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedMethod_ignoreTypePropagation);
@@ -5300,6 +5413,14 @@
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedOperator_plus);
       });
+      _ut.test('test_undefinedOperator_postfixExpression', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_postfixExpression);
+      });
+      _ut.test('test_undefinedOperator_prefixExpression', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_prefixExpression);
+      });
       _ut.test('test_undefinedSetter', () {
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_undefinedSetter);
@@ -5705,6 +5826,122 @@
     assertErrors(source, [HintCode.TYPE_CHECK_IS_NOT_NULL]);
     verify([source]);
   }
+  void test_undefinedGetter() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    return a.m;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_GETTER]);
+  }
+  void test_undefinedGetter_message() {
+    JUnitTestCase.assertEquals(StaticTypeWarningCode.UNDEFINED_GETTER.message, StaticWarningCode.UNDEFINED_GETTER.message);
+  }
+  void test_undefinedMethod() {
+    Source source = addSource(EngineTestCase.createSource([
+        "f() {",
+        "  var a = 'str';",
+        "  a.notAMethodOnString();",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_METHOD]);
+  }
+  void test_undefinedMethod_assignmentExpression() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "class B {",
+        "  f(var a, var a2) {",
+        "    a = new A();",
+        "    a2 = new A();",
+        "    a += a2;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_METHOD]);
+  }
+  void test_undefinedOperator_indexBoth() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a[0]++;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_OPERATOR, HintCode.UNDEFINED_OPERATOR]);
+  }
+  void test_undefinedOperator_indexGetter() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a[0];",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
+  }
+  void test_undefinedOperator_indexSetter() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a[0] = 1;",
+        "  }",
+        "}"]));
+    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 {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a++;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
+  }
+  void test_undefinedOperator_prefixExpression() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    ++a;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
+  }
+  void test_undefinedSetter() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {}",
+        "f(var a) {",
+        "  if(a is A) {",
+        "    a.m = 0;",
+        "  }",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [HintCode.UNDEFINED_SETTER]);
+  }
+  void test_undefinedSetter_message() {
+    JUnitTestCase.assertEquals(StaticTypeWarningCode.UNDEFINED_SETTER.message, StaticWarningCode.UNDEFINED_SETTER.message);
+  }
   void test_unnecessaryCast_type_supertype() {
     Source source = addSource(EngineTestCase.createSource(["m(int i) {", "  var b = i as Object;", "}"]));
     resolve(source);
@@ -5959,6 +6196,54 @@
         final __test = new HintCodeTest();
         runJUnitTest(__test, __test.test_typeCheck_type_not_Null);
       });
+      _ut.test('test_undefinedGetter', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedGetter);
+      });
+      _ut.test('test_undefinedGetter_message', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedGetter_message);
+      });
+      _ut.test('test_undefinedMethod', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedMethod);
+      });
+      _ut.test('test_undefinedMethod_assignmentExpression', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedMethod_assignmentExpression);
+      });
+      _ut.test('test_undefinedOperator_indexBoth', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_indexBoth);
+      });
+      _ut.test('test_undefinedOperator_indexGetter', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_indexGetter);
+      });
+      _ut.test('test_undefinedOperator_indexSetter', () {
+        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);
+      });
+      _ut.test('test_undefinedOperator_prefixExpression', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedOperator_prefixExpression);
+      });
+      _ut.test('test_undefinedSetter', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedSetter);
+      });
+      _ut.test('test_undefinedSetter_message', () {
+        final __test = new HintCodeTest();
+        runJUnitTest(__test, __test.test_undefinedSetter_message);
+      });
       _ut.test('test_unnecessaryCast_type_supertype', () {
         final __test = new HintCodeTest();
         runJUnitTest(__test, __test.test_unnecessaryCast_type_supertype);
@@ -6420,7 +6705,7 @@
    * @throws AssertionFailedError if any errors have been reported
    */
   void assertNoErrors(Source source) {
-    EngineTestCase.assertLength(0, analysisContext.computeErrors(source));
+    assertErrors(source, []);
   }
 
   /**
@@ -16466,16 +16751,16 @@
    * @param body the body of the function
    * @return a resolved function expression
    */
-  FunctionExpression resolvedFunctionExpression(FormalParameterList parameters2, FunctionBody body) {
+  FunctionExpression resolvedFunctionExpression(FormalParameterList parameters, FunctionBody body) {
     List<ParameterElement> parameterElements = new List<ParameterElement>();
-    for (FormalParameter parameter in parameters2.parameters) {
+    for (FormalParameter parameter in parameters.parameters) {
       ParameterElementImpl element = new ParameterElementImpl.con1(parameter.identifier);
       element.parameterKind = parameter.kind;
       element.type = _typeProvider.dynamicType;
       parameter.identifier.staticElement = element;
       parameterElements.add(element);
     }
-    FunctionExpression node = ASTFactory.functionExpression2(parameters2, body);
+    FunctionExpression node = ASTFactory.functionExpression2(parameters, body);
     FunctionElementImpl element = new FunctionElementImpl.con1(null);
     element.parameters = new List.from(parameterElements);
     element.type = new FunctionTypeImpl.con1(element);
@@ -16514,12 +16799,12 @@
    * @param variableName the name of the variable
    * @return a simple identifier that has been resolved to a variable element with the given type
    */
-  SimpleIdentifier resolvedVariable(InterfaceType type2, String variableName) {
+  SimpleIdentifier resolvedVariable(InterfaceType type, String variableName) {
     SimpleIdentifier identifier = ASTFactory.identifier3(variableName);
     VariableElementImpl element = ElementFactory.localVariableElement(identifier);
-    element.type = type2;
+    element.type = type;
     identifier.staticElement = element;
-    identifier.staticType = type2;
+    identifier.staticType = type;
     return identifier;
   }
 
@@ -16529,14 +16814,14 @@
    * @param parameter the parameter whose type is to be set
    * @param type the new type of the given parameter
    */
-  void setType(FormalParameter parameter, Type2 type2) {
+  void setType(FormalParameter parameter, Type2 type) {
     SimpleIdentifier identifier = parameter.identifier;
     Element element = identifier.staticElement;
     if (element is! ParameterElement) {
       element = new ParameterElementImpl.con1(identifier);
       identifier.staticElement = element;
     }
-    ((element as ParameterElementImpl)).type = type2;
+    ((element as ParameterElementImpl)).type = type;
   }
   static dartSuite() {
     _ut.group('StaticTypeAnalyzerTest', () {
@@ -17035,6 +17320,13 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_unusedImport_annotationOnDirective() {
+    Source source = addSource(EngineTestCase.createSource(["library L;", "@A()", "import 'lib1.dart';"]));
+    Source source2 = addSource2("/lib1.dart", EngineTestCase.createSource(["library lib1;", "class A {", "  const A() {}", "}"]));
+    resolve(source);
+    assertErrors(source, []);
+    verify([source, source2]);
+  }
   void test_unusedImport_core_library() {
     Source source = addSource(EngineTestCase.createSource(["library L;", "import 'dart:core';"]));
     resolve(source);
@@ -17169,6 +17461,10 @@
         final __test = new NonHintCodeTest();
         runJUnitTest(__test, __test.test_unnecessaryCast_type_dynamic);
       });
+      _ut.test('test_unusedImport_annotationOnDirective', () {
+        final __test = new NonHintCodeTest();
+        runJUnitTest(__test, __test.test_unusedImport_annotationOnDirective);
+      });
       _ut.test('test_unusedImport_core_library', () {
         final __test = new NonHintCodeTest();
         runJUnitTest(__test, __test.test_unusedImport_core_library);
diff --git a/pkg/analyzer_experimental/test/generated/scanner_test.dart b/pkg/analyzer_experimental/test/generated/scanner_test.dart
index aa74c46..e709c47 100644
--- a/pkg/analyzer_experimental/test/generated/scanner_test.dart
+++ b/pkg/analyzer_experimental/test/generated/scanner_test.dart
@@ -2089,7 +2089,7 @@
   void assertError(ScannerErrorCode expectedError, int expectedOffset, String source) {
     GatheringErrorListener listener = new GatheringErrorListener();
     scan(source, listener);
-    listener.assertErrors([new AnalysisError.con2(null, expectedOffset, 1, expectedError, [(source.codeUnitAt(expectedOffset) as int)])]);
+    listener.assertErrors([new AnalysisError.con2(null, expectedOffset, 1, expectedError, [source.codeUnitAt(expectedOffset) as int])]);
   }
 
   /**
diff --git a/pkg/analyzer_experimental/test/generated/test_support.dart b/pkg/analyzer_experimental/test/generated/test_support.dart
index d0977be..90af45a 100644
--- a/pkg/analyzer_experimental/test/generated/test_support.dart
+++ b/pkg/analyzer_experimental/test/generated/test_support.dart
@@ -232,9 +232,9 @@
    * @param errorCode the error code being searched for
    * @return `true` if an error with the given error code has been gathered
    */
-  bool hasError(ErrorCode errorCode2) {
+  bool hasError(ErrorCode errorCode) {
     for (AnalysisError error in errors) {
-      if (identical(error.errorCode, errorCode2)) {
+      if (identical(error.errorCode, errorCode)) {
         return true;
       }
     }
diff --git a/pkg/analyzer_experimental/test/services/formatter_test.dart b/pkg/analyzer_experimental/test/services/formatter_test.dart
index 51187f3..c2e1f18 100644
--- a/pkg/analyzer_experimental/test/services/formatter_test.dart
+++ b/pkg/analyzer_experimental/test/services/formatter_test.dart
@@ -598,7 +598,8 @@
           '}\n',
           'class A {\n'
           '  int _a;\n'
-          '  A(a) : _a = a;\n'
+          '  A(a)\n'
+          '      : _a = a;\n'
           '}\n'
         );
     });
@@ -622,6 +623,20 @@
         'part of foo;\n'
       );
     });
+    
+    test('CU (cons inits)', () {
+      expectCUFormatsTo('class X {\n'
+          '  var x, y;\n'
+          '  X() : x = 1, y = 2;\n'
+          '}\n', 
+          'class X {\n'
+          '  var x, y;\n'
+          '  X()\n'
+          '      : x = 1,\n' 
+          '        y = 2;\n'
+          '}\n'
+      );
+    });
 
     test('stmt', () {
       expectStmtFormatsTo(
@@ -763,6 +778,21 @@
         '}'
       );
     });
+    
+    test('Statement (if)', () {
+      expectStmtFormatsTo('if (true) print("true!");', 
+                          'if (true) print("true!");');
+      expectStmtFormatsTo('if (true) { print("true!"); }', 
+                          'if (true) {\n'
+                          '  print("true!");\n'
+                          '}');
+      expectStmtFormatsTo('if (true) print("true!"); else print("false!");', 
+                          'if (true) {\n'
+                          '  print("true!");\n'
+                          '} else {\n'
+                          '  print("false!");\n'
+                          '}');
+    }); 
 
     test('initialIndent', () {
       var formatter = new CodeFormatter(
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js
index 40e1700..8577e4f 100644
--- a/pkg/browser/lib/interop.js
+++ b/pkg/browser/lib/interop.js
@@ -224,7 +224,9 @@
 (function() {
   // Proxy support for js.dart.
 
-  var globalContext = window;
+  // We don't use 'window' because we might be in a web worker, but we don't
+  // use 'self' because not all browsers support it
+  var globalContext = function() { return this; }();
 
   // Table for local objects and functions that are proxied.
   function ProxiedObjectTable() {
diff --git a/pkg/custom_element/lib/custom-elements.debug.js b/pkg/custom_element/lib/custom-elements.debug.js
index 843e8a7..a391b8a 100644
--- a/pkg/custom_element/lib/custom-elements.debug.js
+++ b/pkg/custom_element/lib/custom-elements.debug.js
@@ -1207,8 +1207,8 @@
       changeAttribute.call(this, name, value, setAttribute);
     }
     var removeAttribute = prototype.removeAttribute;
-    prototype.removeAttribute = function(name, value) {
-      changeAttribute.call(this, name, value, removeAttribute);
+    prototype.removeAttribute = function(name) {
+      changeAttribute.call(this, name, null, removeAttribute);
     }
   }
 
@@ -1217,7 +1217,7 @@
     operation.apply(this, arguments);
     if (this.attributeChangedCallback
         && (this.getAttribute(name) !== oldValue)) {
-      this.attributeChangedCallback(name, oldValue);
+      this.attributeChangedCallback(name, oldValue, value);
     }
   }
 
diff --git a/pkg/custom_element/lib/custom-elements.min.js b/pkg/custom_element/lib/custom-elements.min.js
index fdec66a..8ecb7a4 100644
--- a/pkg/custom_element/lib/custom-elements.min.js
+++ b/pkg/custom_element/lib/custom-elements.min.js
@@ -25,4 +25,4 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-window.CustomElements={flags:{}};var SideTable;if("undefined"!=typeof WeakMap&&navigator.userAgent.indexOf("Firefox/")<0?SideTable=WeakMap:function(){var a=Object.defineProperty,b=Date.now()%1e9;SideTable=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")},SideTable.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}}}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new SideTable,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g}(this),!window.MutationObserver&&(window.MutationObserver=window.WebKitMutationObserver||window.JsMutationObserver,!MutationObserver))throw new Error("no mutation observer support");!function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),p(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),p(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){_removed(a)}):_removed(a)}function o(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),p(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function p(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function q(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)r(b),b=b.olderShadowRoot}}function r(a){a.__watched||(v(a),a.__watched=!0)}function s(a){switch(a.localName){case"style":case"script":case"template":case void 0:return!0}}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){s(a)||g(a)}),D(a.removedNodes,function(a){s(a)||n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=q,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(g.name=b,!g.prototype)throw new Error("Options missing required prototype property");return g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),m(b,g),g.ctor=n(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeAll(document),g.ctor}function c(a){var b=v[a];return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(w(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a,b){l.call(this,a,b,c)}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments),this.attributeChangedCallback&&this.getAttribute(a)!==d&&this.attributeChangedCallback(a,d)}function m(a,b){if(v[a])throw new Error("Cannot register a tag more than once");v[a]=b}function n(a){return function(){return f(a)}}function o(a,b){var c=v[b||a];if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=o(a);return d.setAttribute("is",b),d}var d=w(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function p(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=v[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function q(b){var c=x.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var r=a.flags,s=Boolean(document.register),t=!r.register&&s;if(t){var u=function(){};a.registry={},a.upgradeElement=u,a.watchShadow=u,a.upgrade=u,a.upgradeAll=u,a.upgradeSubtree=u,a.observeDocument=u,a.upgradeDocument=u,a.takeRecords=u}else{var v={},w=document.createElement.bind(document),x=Node.prototype.cloneNode;document.register=b,document.createElement=o,Node.prototype.cloneNode=q,a.registry=v,a.upgrade=p}a.hasNative=s,a.useNative=t}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(){function a(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState)a();else{var b=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(b,a)}}(),function(){if(HTMLElement.prototype.createShadowRoot){var a=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var b=a.call(this);return b.host=this,b}}}();
+window.CustomElements={flags:{}};var SideTable;if("undefined"!=typeof WeakMap&&navigator.userAgent.indexOf("Firefox/")<0?SideTable=WeakMap:function(){var a=Object.defineProperty,b=Date.now()%1e9;SideTable=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")},SideTable.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}}}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new SideTable,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g}(this),!window.MutationObserver&&(window.MutationObserver=window.WebKitMutationObserver||window.JsMutationObserver,!MutationObserver))throw new Error("no mutation observer support");!function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),p(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),p(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){_removed(a)}):_removed(a)}function o(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),p(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function p(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function q(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)r(b),b=b.olderShadowRoot}}function r(a){a.__watched||(v(a),a.__watched=!0)}function s(a){switch(a.localName){case"style":case"script":case"template":case void 0:return!0}}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){s(a)||g(a)}),D(a.removedNodes,function(a){s(a)||n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=q,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(g.name=b,!g.prototype)throw new Error("Options missing required prototype property");return g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),m(b,g),g.ctor=n(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeAll(document),g.ctor}function c(a){var b=v[a];return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(w(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments),this.attributeChangedCallback&&this.getAttribute(a)!==d&&this.attributeChangedCallback(a,d,b)}function m(a,b){if(v[a])throw new Error("Cannot register a tag more than once");v[a]=b}function n(a){return function(){return f(a)}}function o(a,b){var c=v[b||a];if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=o(a);return d.setAttribute("is",b),d}var d=w(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function p(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=v[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function q(b){var c=x.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var r=a.flags,s=Boolean(document.register),t=!r.register&&s;if(t){var u=function(){};a.registry={},a.upgradeElement=u,a.watchShadow=u,a.upgrade=u,a.upgradeAll=u,a.upgradeSubtree=u,a.observeDocument=u,a.upgradeDocument=u,a.takeRecords=u}else{var v={},w=document.createElement.bind(document),x=Node.prototype.cloneNode;document.register=b,document.createElement=o,Node.prototype.cloneNode=q,a.registry=v,a.upgrade=p}a.hasNative=s,a.useNative=t}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(){function a(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState)a();else{var b=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(b,a)}}(),function(){if(HTMLElement.prototype.createShadowRoot){var a=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var b=a.call(this);return b.host=this,b}}}();
diff --git a/pkg/custom_element/lib/custom_element.dart b/pkg/custom_element/lib/custom_element.dart
index 98bef74..19824cf 100644
--- a/pkg/custom_element/lib/custom_element.dart
+++ b/pkg/custom_element/lib/custom_element.dart
@@ -23,6 +23,8 @@
 import 'package:meta/meta.dart';
 import 'src/custom_tag_name.dart';
 
+part 'src/attribute_map.dart';
+
 // TODO(jmesserly): replace with a real custom element polyfill.
 // This is just something temporary.
 /**
@@ -115,6 +117,7 @@
   /** The web component element wrapped by this class. */
   Element _host;
   List _shadowRoots;
+  _AttributeMap _attributes;
 
   /**
    * Shadow roots generated by dwc for each custom element, indexed by the
@@ -171,6 +174,9 @@
    * Note that [root] will be a [ShadowRoot] if the browser supports Shadow DOM.
    */
   void created() {}
+  // Added for analyzer warnings
+  @deprecated
+  void createdCallback() {}
 
   /** Invoked when this component gets inserted in the DOM tree. */
   void inserted() {}
@@ -182,10 +188,8 @@
   @deprecated
   void leftView() {}
 
-  // TODO(jmesserly): how do we implement this efficiently?
-  // See https://github.com/dart-lang/web-ui/issues/37
   /** Invoked when any attribute of the component is modified. */
-  void attributeChanged(String name, String oldValue, String newValue) {}
+  void attributeChanged(String name, String oldValue) {}
 
   get model => host.model;
 
@@ -272,9 +276,12 @@
   Node insertAllBefore(Iterable<Node> newChild, Node refChild) =>
     host.insertAllBefore(newChild, refChild);
 
-  Map<String, String> get attributes => host.attributes;
+  Map<String, String> get attributes {
+    if (_attributes == null) _attributes = new _AttributeMap(this);
+    return _attributes;
+  }
   set attributes(Map<String, String> value) {
-    host.attributes = value;
+    (attributes as _AttributeMap)._replaceAll(value);
   }
 
   List<Element> get elements => host.children;
@@ -316,10 +323,7 @@
 
   String get nodeValue => host.nodeValue;
 
-  @deprecated
-  // TODO(sigmund): restore the old return type and call host.on when
-  // dartbug.com/8131 is fixed.
-  dynamic get on { throw new UnsupportedError('on is deprecated'); }
+  Events get on => host.on;
 
   String get contentEditable => host.contentEditable;
   set contentEditable(String v) { host.contentEditable = v; }
diff --git a/pkg/custom_element/lib/src/attribute_map.dart b/pkg/custom_element/lib/src/attribute_map.dart
new file mode 100644
index 0000000..8af62c3
--- /dev/null
+++ b/pkg/custom_element/lib/src/attribute_map.dart
@@ -0,0 +1,85 @@
+// 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 custom_element;
+
+/**
+ * Represents an attribute map of model values. If any items are added,
+ * removed, or replaced, then observers that are listening to [changes]
+ * will be notified.
+ */
+class _AttributeMap implements Map<String, String> {
+  final CustomElement _element;
+  final Map<String, String> _map;
+
+  /** Creates an attribute map wrapping the host attributes. */
+  _AttributeMap(CustomElement element)
+      : _element = element, _map = element.host.attributes;
+
+  // Forward all read methods:
+  Iterable<String> get keys => _map.keys;
+  Iterable<String> get values => _map.values;
+  int get length =>_map.length;
+  bool get isEmpty => _map.isEmpty;
+  bool get isNotEmpty => _map.isNotEmpty;
+  bool containsValue(Object value) => _map.containsValue(value);
+  bool containsKey(Object key) => _map.containsKey(key);
+  String operator [](Object key) => _map[key];
+  void forEach(void f(String key, String value)) => _map.forEach(f);
+  String toString() => _map.toString();
+
+  // Override the write methods and ensure attributeChanged is called:
+  void operator []=(String key, String value) {
+    int len = _map.length;
+    String oldValue = _map[key];
+    _map[key] = value;
+    if (len != _map.length || !identical(oldValue, value)) {
+      _element.attributeChanged(key, oldValue);
+    }
+  }
+
+  void addAll(Map<String, String> other) {
+    other.forEach((String key, String value) { this[key] = value; });
+  }
+
+  String putIfAbsent(String key, String ifAbsent()) {
+    int len = _map.length;
+    String result = _map.putIfAbsent(key, ifAbsent);
+    if (len != _map.length) {
+      _element.attributeChanged(key, null);
+    }
+    return result;
+  }
+
+  String remove(Object key) {
+    int len = _map.length;
+    String result =  _map.remove(key);
+    if (len != _map.length) {
+      _element.attributeChanged(key, result);
+    }
+    return result;
+  }
+
+  void clear() {
+    int len = _map.length;
+    if (len > 0) {
+      _map.forEach((key, value) {
+        _element.attributeChanged(key, value);
+      });
+    }
+    _map.clear();
+  }
+
+  /**
+   * This is not a [Map] method. We use it to implement "set attributes", which
+   * is a global replace operation. Rather than [clear] followed by [addAll],
+   * we try to be a bit smarter.
+   */
+  void _replaceAll(Map<String, String> other) {
+    for (var key in keys) {
+      if (!other.containsKey(key)) remove(key);
+    }
+    addAll(other);
+  }
+}
diff --git a/pkg/docgen/test/single_library_test.dart b/pkg/docgen/test/single_library_test.dart
index 78c8a5d..dd4044e 100644
--- a/pkg/docgen/test/single_library_test.dart
+++ b/pkg/docgen/test/single_library_test.dart
@@ -10,7 +10,7 @@
 main() {
   group('Generate docs for', () {
     test('one simple file.', () {
-      var temporaryDir = new Directory('single_library').createTempSync();
+      var temporaryDir = Directory.createSystemTempSync('single_library_');
       var fileName = path.join(temporaryDir.path, 'temp.dart');
       var file = new File(fileName);
       file.writeAsStringSync('''
diff --git a/pkg/observe/lib/src/bind_property.dart b/pkg/observe/lib/src/bind_property.dart
index c8524e7..c35bfb9 100644
--- a/pkg/observe/lib/src/bind_property.dart
+++ b/pkg/observe/lib/src/bind_property.dart
@@ -13,7 +13,7 @@
  *
  *       MyModel() {
  *         ...
- *         _sub = bindProperty(_otherModel, const Symbol('value'),
+ *         _sub = onPropertyChange(_otherModel, const Symbol('value'),
  *             () => notifyProperty(this, const Symbol('prop'));
  *       }
  *
@@ -23,7 +23,8 @@
  *
  * See also [notifyProperty].
  */
-StreamSubscription bindProperty(Observable source, Symbol sourceName,
+// TODO(jmesserly): make this an instance method?
+StreamSubscription onPropertyChange(Observable source, Symbol sourceName,
     void callback()) {
   return source.changes.listen((records) {
     for (var record in records) {
diff --git a/pkg/observe/lib/src/observable.dart b/pkg/observe/lib/src/observable.dart
index d39f84a..c5c56ab 100644
--- a/pkg/observe/lib/src/observable.dart
+++ b/pkg/observe/lib/src/observable.dart
@@ -7,7 +7,7 @@
 /**
  * Use `@observable` to make a field automatically observable.
  */
-const Object observable = const _ObservableAnnotation();
+const ObservableProperty observable = const ObservableProperty();
 
 /**
  * Interface representing an observable object. This is used by data in
@@ -124,7 +124,7 @@
         if (field.isFinal || field.isStatic || field.isPrivate) continue;
 
         for (var meta in field.metadata) {
-          if (identical(observable, meta.reflectee)) {
+          if (meta.reflectee is ObservableProperty) {
             var name = field.simpleName;
             // Note: since this is a field, getting the value shouldn't execute
             // user code, so we don't need to worry about errors.
@@ -220,12 +220,16 @@
 
 
 /**
- * The type of the `@observable` annotation.
+ * An annotation that is used to make a property observable.
+ * Normally this is used via the [observable] constant, for example:
  *
- * Library private because you should be able to use the [observable] field
- * to get the one and only instance. We could make it public though, if anyone
- * needs it for some reason.
+ *     class Monster {
+ *       @observable int health;
+ *     }
+ *
+ * If needed, you can subclass this to create another annotation that will also
+ * be treated as observable.
  */
-class _ObservableAnnotation {
-  const _ObservableAnnotation();
+class ObservableProperty {
+  const ObservableProperty();
 }
diff --git a/pkg/observe/lib/transform.dart b/pkg/observe/lib/transform.dart
index 029a017..d1e8139 100644
--- a/pkg/observe/lib/transform.dart
+++ b/pkg/observe/lib/transform.dart
@@ -34,7 +34,8 @@
     // as much work as applying the transform. We rather have some false
     // positives here, and then generate no outputs when we apply this
     // transform.
-    return input.readAsString().then((c) => c.contains("@observable"));
+    return input.readAsString().then(
+      (c) => c.contains("@observable") || c.contains("@published"));
   }
 
   Future apply(Transform transform) {
@@ -102,8 +103,12 @@
 
 _getSpan(SourceFile file, ASTNode node) => file.span(node.offset, node.end);
 
-/** True if the node has the `@observable` annotation. */
-bool _hasObservable(AnnotatedNode node) => _hasAnnotation(node, 'observable');
+/** True if the node has the `@observable` or `@published` annotation. */
+// TODO(jmesserly): it is not good to be hard coding these. We should do a
+// resolve and do a proper ObservableProperty subtype check. However resolve
+// is very expensive in analyzer_experimental, so it isn't feasible yet.
+bool _hasObservable(AnnotatedNode node) =>
+    _hasAnnotation(node, 'observable') || _hasAnnotation(node, 'published');
 
 bool _hasAnnotation(AnnotatedNode node, String name) {
   // TODO(jmesserly): this isn't correct if the annotation has been imported
@@ -134,7 +139,7 @@
       declaresObservable = true;
     } else if (id.name == 'ChangeNotifierBase') {
       declaresObservable = true;
-    } else if (id.name != 'PolymerElement' && id.name != 'CustomElement'
+    } else if (id.name != 'HtmlElement' && id.name != 'CustomElement'
         && id.name != 'Object') {
       // TODO(sigmund): this is conservative, consider using type-resolution to
       // improve this check.
@@ -183,14 +188,13 @@
       }
       if (_hasObservable(member)) {
         if (!declaresObservable) {
-          logger.warning('Observable fields should be put in an observable'
-              ' objects. Please declare that this class extends from '
+          logger.warning('Observable fields should be put in an observable '
+              'objects. Please declare that this class extends from '
               'ObservableBase, includes ObservableMixin, or implements '
               'Observable.',
               _getSpan(file, member));
-
         }
-        _transformFields(member.fields, code, member.offset, member.end);
+        _transformFields(file, member, code, logger);
 
         var names = member.fields.variables.map((v) => v.name.name);
 
@@ -289,40 +293,89 @@
       _hasKeyword(fields.keyword, Keyword.FINAL);
 }
 
-void _transformFields(VariableDeclarationList fields, TextEditTransaction code,
-    int begin, int end) {
+void _transformFields(SourceFile file, FieldDeclaration member,
+    TextEditTransaction code, TransformLogger logger) {
 
+  final fields = member.fields;
   if (_isReadOnly(fields)) return;
 
-  var indent = guessIndent(code.original, begin);
-  var replace = new StringBuffer();
+  // Private fields aren't supported:
+  for (var field in fields.variables) {
+    final name = field.name.name;
+    if (Identifier.isPrivateName(name)) {
+      logger.warning('Cannot make private field $name observable.',
+          _getSpan(file, field));
+      return;
+    }
+  }
 
   // Unfortunately "var" doesn't work in all positions where type annotations
   // are allowed, such as "var get name". So we use "dynamic" instead.
   var type = 'dynamic';
   if (fields.type != null) {
     type = _getOriginalCode(code, fields.type);
+  } else if (_hasKeyword(fields.keyword, Keyword.VAR)) {
+    // Replace 'var' with 'dynamic'
+    code.edit(fields.keyword.offset, fields.keyword.end, type);
   }
 
-  for (var field in fields.variables) {
-    var initializer = '';
-    if (field.initializer != null) {
-      initializer = ' = ${_getOriginalCode(code, field.initializer)}';
-    }
+  // Note: the replacements here are a bit subtle. It needs to support multiple
+  // fields declared via the same @observable, as well as preserving newlines.
+  // (Preserving newlines is important because it allows the generated code to
+  // be debugged without needing a source map.)
+  //
+  // For example:
+  //
+  //     @observable
+  //     @otherMetaData
+  //         Foo
+  //             foo = 1, bar = 2,
+  //             baz;
+  //
+  // Will be transformed into something like:
+  //
+  //     @observable
+  //     @OtherMetaData()
+  //         Foo
+  //             get foo => __foo; Foo __foo = 1; set foo ...; ... bar ...
+  //             @observable @OtherMetaData() Foo get baz => __baz; Foo baz; ...
+  //
+  // Metadata is moved to the getter.
 
-    var name = field.name.name;
+  String metadata = '';
+  if (fields.variables.length > 1) {
+    metadata = member.metadata
+      .map((m) => _getOriginalCode(code, m))
+      .join(' ');
+  }
 
-    // TODO(jmesserly): should we generate this one one line, so source maps
-    // don't break?
-    if (replace.length > 0) replace.write('\n\n$indent');
-    replace.write('''
-$type __\$$name$initializer;
-$type get $name => __\$$name;
-set $name($type value) {
-  __\$$name = notifyPropertyChange(const Symbol('$name'), __\$$name, value);
+  for (int i = 0; i < fields.variables.length; i++) {
+    final field = fields.variables[i];
+    final name = field.name.name;
+
+    var beforeInit = 'get $name => __\$$name; $type __\$$name';
+
+    // The first field is expanded differently from subsequent fields, because
+    // we can reuse the metadata and type annotation.
+    if (i > 0) beforeInit = '$metadata $type $beforeInit';
+
+    code.edit(field.name.offset, field.name.end, beforeInit);
+
+    // Replace comma with semicolon
+    final end = _findFieldSeperator(field.endToken.next);
+    if (end.type == TokenType.COMMA) code.edit(end.offset, end.end, ';');
+
+    code.edit(end.end, end.end, ' set $name($type value) { '
+        '__\$$name = notifyPropertyChange(#$name, __\$$name, value); }');
+  }
 }
-'''.replaceAll('\n', '\n$indent'));
-  }
 
-  code.edit(begin, end, '$replace');
+Token _findFieldSeperator(Token token) {
+  while (token != null) {
+    if (token.type == TokenType.COMMA || token.type == TokenType.SEMICOLON) {
+      break;
+    }
+    token = token.next;
+  }
+  return token;
 }
diff --git a/pkg/observe/test/transform_test.dart b/pkg/observe/test/transform_test.dart
index 9a64fac..5a4b138 100644
--- a/pkg/observe/test/transform_test.dart
+++ b/pkg/observe/test/transform_test.dart
@@ -47,17 +47,24 @@
     _testInitializers('this.a, {this.b}', '(a, {b}) : __\$a = a, __\$b = b');
   });
 
-  group('test full text', () {
-    test('with changes', () {
-      return _transform(_sampleObservable('A', 'foo'))
-        .then((output) => expect(output, _sampleObservableOutput('A', 'foo')));
-    });
+  for (var annotation in ['observable', 'published']) {
+    group('@$annotation full text', () {
+      test('with changes', () {
+        return _transform(_sampleObservable(annotation)).then(
+            (out) => expect(out, _sampleObservableOutput(annotation)));
+      });
 
-    test('no changes', () {
-      var input = 'class A {/*@observable annotation to trigger transform */;}';
-      return _transform(input).then((output) => expect(output, input));
+      test('complex with changes', () {
+        return _transform(_complexObservable(annotation)).then(
+            (out) => expect(out, _complexObservableOutput(annotation)));
+      });
+
+      test('no changes', () {
+        var input = 'class A {/*@$annotation annotation to trigger transform */;}';
+        return _transform(input).then((output) => expect(output, input));
+      });
     });
-  });
+  }
 }
 
 _testClause(String clauses, String expected) {
@@ -121,37 +128,64 @@
   Asset get primaryInput => _asset;
 
   _MockTransform(this._asset);
-  Future<Asset> getInput(Asset id) {
+  Future<Asset> getInput(AssetId id) {
     if (id == primaryInput.id) return new Future.value(primaryInput);
-    fail();
+    fail('_MockTransform fail');
   }
 
   void addOutput(Asset output) {
     outs.add(output);
   }
+
+  readInput(id) => throw new UnimplementedError();
+  readInputAsString(id, {encoding}) => throw new UnimplementedError();
 }
 
-String _sampleObservable(String className, String fieldName) => '''
-library ${className}_$fieldName;
+String _sampleObservable(String annotation) => '''
+library A_foo;
 import 'package:observe/observe.dart';
 
-class $className extends ObservableBase {
-  @observable int $fieldName;
-  $className(this.$fieldName);
+class A extends ObservableBase {
+  @$annotation int foo;
+  A(this.foo);
 }
 ''';
 
-String _sampleObservableOutput(String className, String fieldName) => '''
-library ${className}_$fieldName;
-import 'package:observe/observe.dart';
+String _sampleObservableOutput(String annotation) =>
+    "library A_foo;\n"
+    "import 'package:observe/observe.dart';\n\n"
+    "class A extends ChangeNotifierBase {\n"
+    "  @$annotation int get foo => __\$foo; int __\$foo; "
+      "${_makeSetter('int', 'foo')}\n"
+    "  A(foo) : __\$foo = foo;\n"
+    "}\n";
 
-class $className extends ChangeNotifierBase {
-  int __\$$fieldName;
-  int get $fieldName => __\$$fieldName;
-  set $fieldName(int value) {
-    __\$$fieldName = notifyPropertyChange(const Symbol('$fieldName'), __\$$fieldName, value);
-  }
-  
-  $className($fieldName) : __\$$fieldName = $fieldName;
+_makeSetter(type, name) => 'set $name($type value) { '
+    '__\$$name = notifyPropertyChange(#$name, __\$$name, value); }';
+
+String _complexObservable(String annotation) => '''
+class Foo extends ObservableBase {
+  @$annotation
+  @otherMetadata
+      Foo
+          foo/*D*/= 1, bar =/*A*/2/*B*/,
+          quux/*C*/;
+
+  @$annotation var baz;
 }
 ''';
+
+String _complexObservableOutput(String annotation) =>
+    "class Foo extends ChangeNotifierBase {\n"
+    "  @$annotation\n"
+    "  @otherMetadata\n"
+    "      Foo\n"
+    "          get foo => __\$foo; Foo __\$foo/*D*/= 1; "
+        "${_makeSetter('Foo', 'foo')} "
+        "@$annotation @otherMetadata Foo get bar => __\$bar; "
+        "Foo __\$bar =/*A*/2/*B*/; ${_makeSetter('Foo', 'bar')}\n"
+    "          @$annotation @otherMetadata Foo get quux => __\$quux; "
+        "Foo __\$quux/*C*/; ${_makeSetter('Foo', 'quux')}\n\n"
+    "  @$annotation dynamic get baz => __\$baz; dynamic __\$baz; "
+        "${_makeSetter('dynamic', 'baz')}\n"
+    "}\n";
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 9ff7d8d..d5c5205 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -57,24 +57,42 @@
 stack_trace/test/trace_test: Fail # http://dartbug.com/12380
 crypto/test/sha256_test: Pass, Fail # Issue 12502
 crypto/test/hmac_sha256_test: Pass, Fail # Issue 12502
-polymer/test/events_test: Fail # Issue 12865, 13197
+polymer/test/attr_deserialize_test: Fail # Issue 12865, 13197
+polymer/test/attr_mustache_test: Fail # Issue 12865, 13197
 polymer/test/event_path_test: Fail # Issue 12865, 13197
+polymer/test/events_test: Fail # Issue 12865, 13197
+polymer/test/prop_attr_reflection_test: Fail # Issue 12865, 13197
 
 [ $runtime == ie9 || $runtime == ie10 ]
-polymer/test/events_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/attr_deserialize_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/attr_mustache_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/event_path_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/events_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/prop_attr_reflection_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/publish_attributes_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/take_attributes_test: Fail, Timeout # Issue 12865, 13197, 13260
 
 [ $system == windows && ($runtime == chrome || $runtime == ff) ]
-polymer/test/events_test: Pass, Timeout # Issue 13260
+polymer/test/attr_deserialize_test: Pass, Timeout # Issue 13260
+polymer/test/attr_mustache_test: Pass, Timeout # Issue 13260
 polymer/test/event_path_test: Pass, Timeout # Issue 13260
+polymer/test/events_test: Pass, Timeout # Issue 13260
+polymer/test/prop_attr_reflection_test: Pass, Timeout # Issue 13260
+polymer/test/publish_attributes_test: Pass, Timeout # Issue 13260
+polymer/test/take_attributes_test: Pass, Timeout # Issue 13260
 
 # Skip browser-specific tests on VM
 [ $runtime == vm ]
 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/events_test: Fail, OK # Uses dart:html
+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/prop_attr_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 ]
@@ -140,7 +158,6 @@
 observe/test/transform_test: Fail, OK # Uses dart:io.
 path/test/io_test: Fail, OK # Uses dart:io.
 polymer/test/build/*: Fail, OK # Uses dart:io.
-polymer/test/utils_test: Fail, OK # Uses dart:io.
 watcher/test/*: Fail, OK # Uses dart:io.
 
 scheduled_test/test/descriptor/async_test: Fail # http://dartbug.com/8440
@@ -182,17 +199,17 @@
 # not minified.
 unittest/test/*_minified_test: Skip # DO NOT COPY THIS UNLESS YOU WORK ON DART2JS
 
+[ $arch == mips ]
+*: Skip  # Issue 13650
+
 [ $arch == arm ]
-*: Skip
+*: Skip  # Issue 13624
 
 [ $arch == simarm ]
-*: Skip
+watcher/test/no_subscription_test: Pass, Fail  # Issue 13705.
 
-[ $arch == mips ]
-*: Skip
-
-[ $arch == simmips ]
-*: Skip
+[ $arch == simarm || $arch == simmips ]
+third_party/html5lib/test/tokenizer_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.
diff --git a/pkg/polymer/example/component/news/web/news-component.html b/pkg/polymer/example/component/news/web/news-component.html
index 7f63f54..70254b8 100644
--- a/pkg/polymer/example/component/news/web/news-component.html
+++ b/pkg/polymer/example/component/news/web/news-component.html
@@ -31,7 +31,7 @@
 
     @initMethod
     _init() {
-      registerPolymerElement('x-news', () => new XNews());
+      Polymer.register('x-news', XNews);
     }
   </script>
 </polymer-element>
diff --git a/pkg/polymer/lib/boot.js b/pkg/polymer/lib/boot.js
index 0a3fe62..2bcb590 100644
--- a/pkg/polymer/lib/boot.js
+++ b/pkg/polymer/lib/boot.js
@@ -56,8 +56,30 @@
       ' tool to compile a depolyable JavaScript version')
     return;
   }
-  document.write(
-    '<script src="packages/html_import/html_import.min.js"></script>');
+
+
+  // Load HTML Imports:
+  var htmlImportsSrc = 'src="packages/html_import/html_import.min.js"';
+  document.write('<script ' + htmlImportsSrc + '></script>');
+  var importScript = document.querySelector('script[' + htmlImportsSrc + ']');
+  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.
diff --git a/pkg/polymer/lib/component_build.dart b/pkg/polymer/lib/component_build.dart
index 6a923f0..cdd0820 100644
--- a/pkg/polymer/lib/component_build.dart
+++ b/pkg/polymer/lib/component_build.dart
@@ -6,6 +6,7 @@
 @deprecated
 library build_utils;
 
+import 'dart:async';
 import 'package:meta/meta.dart';
 
 import 'builder.dart' as builder;
@@ -18,5 +19,5 @@
 Future build(List<String> arguments, List<String> entryPoints,
     {bool printTime: true, bool shouldPrint: true}) {
   return builder.build(
-      entryPoints: entryPoints, options: parseOptions(arguments));
+      entryPoints: entryPoints, options: builder.parseOptions(arguments));
 }
diff --git a/pkg/polymer/lib/deserialize.dart b/pkg/polymer/lib/deserialize.dart
new file mode 100644
index 0000000..7f72c2c
--- /dev/null
+++ b/pkg/polymer/lib/deserialize.dart
@@ -0,0 +1,51 @@
+// 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 polymer.deserialize;
+
+import 'dart:convert' show JSON;
+import 'dart:mirrors' show reflect, TypeMirror;
+
+final _typeHandlers = () {
+  // TODO(jmesserly): switch to map and symbol literal form when supported.
+  var m = new Map();
+  m[const Symbol('dart.core.String')] = (x, _) => x;
+  m[const Symbol('dart.core.Null')] = (x, _) => x;
+  m[const Symbol('dart.core.DateTime')] = (x, _) {
+    // TODO(jmesserly): shouldn't need to try-catch here
+    // See: https://code.google.com/p/dart/issues/detail?id=1878
+    try {
+      return DateTime.parse(x);
+    } catch (e) {
+      return new DateTime.now();
+    }
+  };
+  m[const Symbol('dart.core.bool')] = (x, _) => x != 'false';
+  m[const Symbol('dart.core.int')] =
+      (x, def) => int.parse(x, onError: (_) => def);
+  m[const Symbol('dart.core.double')] =
+      (x, def) => double.parse(x, (_) => def);
+  return m;
+}();
+
+/**
+ * Convert representation of [value] based on type of [defaultValue].
+ */
+Object deserializeValue(String value, Object defaultValue, TypeMirror type) {
+  var handler = _typeHandlers[type.qualifiedName];
+  if (handler != null) return handler(value, defaultValue);
+
+  try {
+    // If the string is an object, we can parse is with the JSON library.
+    // include convenience replace for single-quotes. If the author omits
+    // quotes altogether, parse will fail.
+    return JSON.decode(value.replaceAll("'", '"'));
+
+    // TODO(jmesserly): deserialized JSON is not assignable to most objects in
+    // Dart. We should attempt to convert it appropriately.
+  } catch(e) {
+    // The object isn't valid JSON, return the raw value
+    return value;
+  }
+}
diff --git a/pkg/polymer/lib/job.dart b/pkg/polymer/lib/job.dart
new file mode 100644
index 0000000..677784a
--- /dev/null
+++ b/pkg/polymer/lib/job.dart
@@ -0,0 +1,53 @@
+// 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 polymer.job;
+
+import 'dart:async' show Timer;
+
+/**
+ * Invoke [callback] in [wait], unless the job is re-registered,
+ * which resets the timer. For example:
+ *
+ *     _myJob = runJob(_myJob, callback, const Duration(milliseconds: 100));
+ *
+ * Returns a job handle which can be used to re-register a job.
+ */
+// Dart note: renamed to runJob to avoid conflict with instance member "job".
+Job runJob(Job job, void callback(), Duration wait) {
+  if (job != null) {
+    job.stop();
+  } else {
+    job = new Job();
+  }
+  job.go(callback, wait);
+  return job;
+}
+
+// TODO(jmesserly): it isn't clear to me what is supposed to be public API here.
+// Or what name we should use. "Job" is awfully generic.
+// (The type itself is not exported in Polymer.)
+class Job {
+  Function _callback;
+  Timer _timer;
+
+  void go(void callback(), Duration wait) {
+    this._callback = callback;
+    _timer = new Timer(wait, complete);
+  }
+
+  void stop() {
+    if (_timer != null) {
+      _timer.cancel();
+      _timer = null;
+    }
+  }
+
+  void complete() {
+    if (_timer != null) {
+      stop();
+      _callback();
+    }
+  }
+}
diff --git a/pkg/polymer/lib/platform.dart b/pkg/polymer/lib/platform.dart
new file mode 100644
index 0000000..5dc5c3e
--- /dev/null
+++ b/pkg/polymer/lib/platform.dart
@@ -0,0 +1,41 @@
+// 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.
+
+/**
+ * Exposes helper functionality for interacting with the platform. Similar to
+ * the [Platform] class from dart:html.
+ */
+// TODO(jmesserly): in Polymer this is a static class called "Platform", but
+// that conflicts with dart:html. What should we do? Does this functionality
+// belong in html's Platform instead?
+library polymer.platform;
+
+import 'dart:html' show Text, MutationObserver;
+import 'dart:collection' show Queue;
+import 'package:observe/src/microtask.dart' show performMicrotaskCheckpoint;
+
+void flush() {
+  endOfMicrotask(performMicrotaskCheckpoint);
+}
+
+int _iterations = 0;
+final Queue _callbacks = new Queue();
+final Text _twiddle = () {
+  var twiddle = new Text('');
+  new MutationObserver((x, y) {
+    while (_callbacks.isNotEmpty) {
+      try {
+        _callbacks.removeFirst()();
+      } catch (e) { // Dart note: fire the error async.
+        new Completer().completeError(e);
+      }
+    }
+  }).observe(twiddle, characterData: true);
+  return twiddle;
+}();
+
+void endOfMicrotask(void callback()) {
+  _twiddle.text = '${_iterations++}';
+  _callbacks.add(callback);
+}
diff --git a/pkg/polymer/lib/polymer.dart b/pkg/polymer/lib/polymer.dart
index e417fe5..a7ae73f 100644
--- a/pkg/polymer/lib/polymer.dart
+++ b/pkg/polymer/lib/polymer.dart
@@ -40,136 +40,31 @@
 library polymer;
 
 import 'dart:async';
+import 'dart:collection' show HashMap;
+import 'dart:html';
+import 'dart:js' as js;
 import 'dart:mirrors';
 
+import 'package:custom_element/custom_element.dart';
+import 'package:logging/logging.dart' show Logger, Level;
 import 'package:mdv/mdv.dart' as mdv;
+import 'package:mdv/mdv.dart' show NodeBinding;
+import 'package:meta/meta.dart' show deprecated;
+import 'package:observe/observe.dart';
 import 'package:observe/src/microtask.dart';
 import 'package:path/path.dart' as path;
-import 'polymer_element.dart' show registerPolymerElement;
+import 'package:polymer_expressions/polymer_expressions.dart'
+    show PolymerExpressions;
+
+import 'deserialize.dart' as deserialize;
+import 'job.dart';
+import 'platform.dart' as platform;
 
 export 'package:custom_element/custom_element.dart';
 export 'package:observe/observe.dart';
 export 'package:observe/html.dart';
 export 'package:observe/src/microtask.dart';
 
-export 'polymer_element.dart';
-
-
-/** Annotation used to automatically register polymer elements. */
-class CustomTag {
-  final String tagName;
-  const CustomTag(this.tagName);
-}
-
-/**
- * Metadata used to label static or top-level methods that are called
- * automatically when loading the library of a custom element.
- */
-const initMethod = const _InitMethodAnnotation();
-
-/**
- * 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.
- *
- * The initialization on each library is either a method named `main` or
- * a top-level function and annotated with [initMethod].
- *
- * The urls in [libraries] can be absolute or relative to [srcUrl].
- */
-void initPolymer(List<String> libraries, [String srcUrl]) {
-  wrapMicrotask(() {
-    // DOM events don't yet go through microtasks, so we catch those here.
-    new Timer.periodic(new Duration(milliseconds: 125),
-        (_) => performMicrotaskCheckpoint());
-
-    // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize.
-    mdv.initialize();
-    for (var lib in libraries) {
-      _loadLibrary(lib, srcUrl);
-    }
-  })();
-}
-
-/** All libraries in the current isolate. */
-final _libs = currentMirrorSystem().libraries;
-
-/**
- * Reads the library at [uriString] (which can be an absolute URI or a relative
- * URI from [srcUrl]), and:
- *
- *   * If present, invokes `main`.
- *
- *   * If present, invokes any top-level and static functions marked
- *     with the [initMethod] annotation (in the order they appear).
- *
- *   * 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)));
-  }
-  var lib = _libs[uri];
-  if (lib == null) {
-    print('warning: $uri library not found');
-    return;
-  }
-
-  // Invoke `main`, if present.
-  if (lib.functions[const Symbol('main')] != null) {
-    lib.invoke(const Symbol('main'), const []);
-  }
-
-  // Search top-level functions marked with @initMethod
-  for (var f in lib.functions.values) {
-    _maybeInvoke(lib, f);
-  }
-
-  for (var c in lib.classes.values) {
-    // Search for @CustomTag on classes
-    for (var m in c.metadata) {
-      var meta = m.reflectee;
-      if (meta is CustomTag) {
-        registerPolymerElement(meta.tagName,
-            () => c.newInstance(const Symbol(''), const []).reflectee);
-      }
-    }
-
-    // TODO(sigmund): check also static methods marked with @initMethod.
-    // This is blocked on two bugs:
-    //  - dartbug.com/12133 (static methods are incorrectly listed as top-level
-    //    in dart2js, so they end up being called twice)
-    //  - dartbug.com/12134 (sometimes "method.metadata" throws an exception,
-    //    we could wrap and hide those exceptions, but it's not ideal).
-  }
-}
-
-void _maybeInvoke(ObjectMirror obj, MethodMirror method) {
-  var annotationFound = false;
-  for (var meta in method.metadata) {
-    if (identical(meta.reflectee, initMethod)) {
-      annotationFound = true;
-      break;
-    }
-  }
-  if (!annotationFound) return;
-  if (!method.isStatic) {
-    print("warning: methods marked with @initMethod should be static,"
-        " ${method.simpleName} is not.");
-    return;
-  }
-  if (!method.parameters.where((p) => !p.isOptional).isEmpty) {
-    print("warning: methods marked with @initMethod should take no "
-        "arguments, ${method.simpleName} expects some.");
-    return;
-  }
-  obj.invoke(method.simpleName, const []);
-}
-
-class _InitMethodAnnotation {
-  const _InitMethodAnnotation();
-}
+part 'src/declaration.dart';
+part 'src/instance.dart';
+part 'src/loader.dart';
diff --git a/pkg/polymer/lib/polymer_element.dart b/pkg/polymer/lib/polymer_element.dart
index a7ade34..c004985 100644
--- a/pkg/polymer/lib/polymer_element.dart
+++ b/pkg/polymer/lib/polymer_element.dart
@@ -4,555 +4,4 @@
 
 library polymer.polymer_element;
 
-import 'dart:async';
-import 'dart:html';
-import 'dart:mirrors';
-import 'dart:js' as js;
-
-import 'package:custom_element/custom_element.dart';
-import 'package:mdv/mdv.dart' show NodeBinding;
-import 'package:observe/observe.dart';
-import 'package:observe/src/microtask.dart';
-import 'package:polymer_expressions/polymer_expressions.dart';
-
-import 'src/utils.dart' show toCamelCase, toHyphenedName;
-
-/**
- * Registers a [PolymerElement]. This is similar to [registerCustomElement]
- * but it is designed to work with the `<element>` element and adds additional
- * features.
- */
-void registerPolymerElement(String localName, PolymerElement create()) {
-  registerCustomElement(localName, () => create().._initialize(localName));
-}
-
-/**
- * *Warning*: many features of this class are not fully implemented.
- *
- * The base class for Polymer elements. It provides convience features on top
- * of the custom elements web standard.
- *
- * Currently it supports publishing attributes via:
- *
- *     <element name="..." attributes="foo, bar, baz">
- *
- * Any attribute published this way can be used in a data binding expression,
- * and it should contain a corresponding DOM field.
- *
- * *Warning*: due to dart2js mirror limititations, the mapping from HTML
- * attribute to element property is a conversion from `dash-separated-words`
- * to camelCase, rather than searching for a property with the same name.
- */
-// TODO(jmesserly): fix the dash-separated-words issue. Polymer uses lowercase.
-class PolymerElement extends CustomElement with _EventsMixin {
-  // This is a partial port of:
-  // https://github.com/Polymer/polymer/blob/stable/src/attrs.js
-  // https://github.com/Polymer/polymer/blob/stable/src/bindProperties.js
-  // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js
-  // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js
-  // TODO(jmesserly): we still need to port more of the functionality
-
-  /// The one syntax to rule them all.
-  static BindingDelegate _polymerSyntax = new PolymerExpressions();
-  // TODO(sigmund): delete. The next line is only added to avoid warnings from
-  // the analyzer (see http://dartbug.com/11672)
-  Element get host => super.host;
-
-  bool get applyAuthorStyles => false;
-  bool get resetStyleInheritance => false;
-
-  /**
-   * The declaration of this polymer-element, used to extract template contents
-   * and other information.
-   */
-  static Map<String, Element> _declarations = {};
-  static Element getDeclaration(String localName) {
-    if (localName == null) return null;
-    var element = _declarations[localName];
-    if (element == null) {
-      element = document.query('polymer-element[name="$localName"]');
-      _declarations[localName] = element;
-    }
-    return element;
-  }
-
-  Map<String, PathObserver> _publishedAttrs;
-  Map<String, StreamSubscription> _bindings;
-  final List<String> _localNames = [];
-
-  void _initialize(String localName) {
-    if (localName == null) return;
-
-    var declaration = getDeclaration(localName);
-    if (declaration == null) return;
-
-    var extendee = declaration.attributes['extends'];
-    if (extendee != null) {
-      // Skip normal tags, only initialize parent custom elements.
-      if (extendee.contains('-')) _initialize(extendee);
-    }
-
-    _parseHostEvents(declaration);
-    _parseLocalEvents(declaration);
-    _publishAttributes(declaration);
-
-    var templateContent = declaration.query('template').content;
-    _shimStyling(templateContent, localName);
-
-    _localNames.add(localName);
-  }
-
-  void _publishAttributes(elementElement) {
-    _bindings = {};
-    _publishedAttrs = {};
-
-    var attrs = elementElement.attributes['attributes'];
-    if (attrs != null) {
-      // attributes='a b c' or attributes='a,b,c'
-      for (var name in attrs.split(attrs.contains(',') ? ',' : ' ')) {
-        name = name.trim();
-
-        // TODO(jmesserly): PathObserver is overkill here; it helps avoid
-        // "new Symbol" and other mirrors-related warnings.
-        _publishedAttrs[name] = new PathObserver(this, toCamelCase(name));
-      }
-    }
-  }
-
-  void created() {
-    // TODO(jmesserly): this breaks until we get some kind of type conversion.
-    // _publishedAttrs.forEach((name, propObserver) {
-    // var value = attributes[name];
-    //   if (value != null) propObserver.value = value;
-    // });
-    _initShadowRoot();
-    _addHostListeners();
-  }
-
-  /**
-   * Creates the document fragment to use for each instance of the custom
-   * element, given the `<template>` node. By default this is equivalent to:
-   *
-   *     template.createInstance(this, polymerSyntax);
-   *
-   * Where polymerSyntax is a singleton `PolymerExpressions` instance from the
-   * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions)
-   * package.
-   *
-   * You can override this method to change the instantiation behavior of the
-   * template, for example to use a different data-binding syntax.
-   */
-  DocumentFragment instanceTemplate(Element template) =>
-      template.createInstance(this, _polymerSyntax);
-
-  void _initShadowRoot() {
-    for (var localName in _localNames) {
-      var declaration = getDeclaration(localName);
-      var root = createShadowRoot(localName);
-      _addInstanceListeners(root, localName);
-
-      root.applyAuthorStyles = applyAuthorStyles;
-      root.resetStyleInheritance = resetStyleInheritance;
-
-      var templateNode = declaration.query('template');
-      if (templateNode == null) return;
-
-      // Create the contents of the element's ShadowRoot, and add them.
-      root.nodes.add(instanceTemplate(templateNode));
-    }
-  }
-
-  NodeBinding createBinding(String name, model, String path) {
-    var propObserver = _publishedAttrs[name];
-    if (propObserver != null) {
-      return new _PolymerBinding(this, name, model, path, propObserver);
-    }
-    return super.createBinding(name, model, path);
-  }
-
-  /**
-   * Using Polymer's platform/src/ShadowCSS.js passing the style tag's content.
-   */
-  void _shimStyling(DocumentFragment template, String localName) {
-    if (js.context == null) return;
-
-    var platform = js.context['Platform'];
-    if (platform == null) return;
-
-    var style = template.query('style');
-    if (style == null) return;
-
-    var shadowCss = platform['ShadowCSS'];
-    if (shadowCss == null) return;
-
-    // TODO(terry): Remove calls to shimShadowDOMStyling2 and replace with
-    //              shimShadowDOMStyling when we support unwrapping dart:html
-    //              Element to a JS DOM node.
-    var shimShadowDOMStyling2 = shadowCss['shimShadowDOMStyling2'];
-    if (shimShadowDOMStyling2 == null) return;
-
-    var scopedCSS = shimShadowDOMStyling2.apply(shadowCss,
-        [style.text, localName]);
-
-    // TODO(terry): Remove when shimShadowDOMStyling is called we don't need to
-    //              replace original CSS with scoped CSS shimShadowDOMStyling
-    //              does that.
-    style.text = scopedCSS;
-  }
-}
-
-class _PolymerBinding extends NodeBinding {
-  final PathObserver _publishedAttr;
-
-  _PolymerBinding(node, property, model, path, PathObserver this._publishedAttr)
-      : super(node, property, model, path);
-
-  void boundValueChanged(newValue) {
-    _publishedAttr.value = newValue;
-  }
-}
-
-/**
- * Polymer features to handle the syntactic sugar on-* to declare to
- * automatically map event handlers to instance methods of the [PolymerElement].
- * This mixin is a port of:
- * https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js
- * https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js
- */
-abstract class _EventsMixin {
-  // TODO(sigmund): implement the Dart equivalent of 'inheritDelegates'
-  // Notes about differences in the implementation below:
-  //  - _templateDelegates: polymer stores the template delegates directly on
-  //    the template node (see in parseLocalEvents: 't.delegates = {}'). Here we
-  //    simply use a separate map, where keys are the name of the
-  //    custom-element.
-  //  - _listenLocal we return true/false and propagate that up, JS
-  //    implementation does't forward the return value.
-  //  - we don't keep the side-table (weak hash map) of unhandled events (see
-  //    handleIfNotHandled)
-  //  - we don't use event.type to dispatch events, instead we save the event
-  //    name with the event listeners. We do so to avoid translating back and
-  //    forth between Dom and Dart event names.
-
-  // ---------------------------------------------------------------------------
-  // The following section was ported from:
-  // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js
-  // ---------------------------------------------------------------------------
-
-  /** Maps event names and their associated method in the element class. */
-  final Map<String, String> _delegates = {};
-
-  /** Expected events per element node. */
-  // TODO(sigmund): investigate whether we need more than 1 set of local events
-  // per element (why does the js implementation stores 1 per template node?)
-  final Map<String, Set<String>> _templateDelegates =
-      new Map<String, Set<String>>();
-
-  /** [host] is needed by this mixin, but not defined here. */
-  Element get host;
-
-  /** Attribute prefix used for declarative event handlers. */
-  static const _eventPrefix = 'on-';
-
-  /** Whether an attribute declares an event. */
-  static bool _isEvent(String attr) => attr.startsWith(_eventPrefix);
-
-  /** Extracts events from the element tag attributes. */
-  void _parseHostEvents(elementElement) {
-    for (var attr in elementElement.attributes.keys.where(_isEvent)) {
-      _delegates[toCamelCase(attr)] = elementElement.attributes[attr];
-    }
-  }
-
-  /** Extracts events under the element's <template>. */
-  void _parseLocalEvents(elementElement) {
-    var name = elementElement.attributes["name"];
-    if (name == null) return;
-    var events = null;
-    for (var template in elementElement.queryAll('template')) {
-      var content = template.content;
-      if (content != null) {
-        for (var child in content.children) {
-          events = _accumulateEvents(child, events);
-        }
-      }
-    }
-    if (events != null) {
-      _templateDelegates[name] = events;
-    }
-  }
-
-  /** Returns all events names listened by [element] and it's children. */
-  static Set<String> _accumulateEvents(Element element, [Set<String> events]) {
-    events = events == null ? new Set<String>() : events;
-
-    // from: accumulateAttributeEvents, accumulateEvent
-    events.addAll(element.attributes.keys.where(_isEvent).map(toCamelCase));
-
-    // from: accumulateChildEvents
-    for (var child in element.children) {
-      _accumulateEvents(child, events);
-    }
-
-    // from: accumulateTemplatedEvents
-    if (element.isTemplate) {
-      var content = element.content;
-      if (content != null) {
-        for (var child in content.children) {
-          _accumulateEvents(child, events);
-        }
-      }
-    }
-    return events;
-  }
-
-  // ---------------------------------------------------------------------------
-  // The following section was ported from:
-  // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js
-  // ---------------------------------------------------------------------------
-
-  /** Attaches event listeners on the [host] element. */
-  void _addHostListeners() {
-    for (var eventName in _delegates.keys) {
-      _addNodeListener(host, eventName,
-          (e) => _hostEventListener(eventName, e));
-    }
-  }
-
-  void _addNodeListener(node, String onEvent, Function listener) {
-    // If [node] is an element (typically when listening for host events) we
-    // use directly the '.onFoo' event stream of the element instance.
-    if (node is Element) {
-      reflect(node).getField(new Symbol(onEvent)).reflectee.listen(listener);
-      return;
-    }
-
-    // When [node] is not an element, most commonly when [node] is the
-    // shadow-root of the polymer-element, we find the appropriate static event
-    // stream providers and attach it to [node].
-    var eventProvider = _eventStreamProviders[onEvent];
-    if (eventProvider != null) {
-      eventProvider.forTarget(node).listen(listener);
-      return;
-    }
-
-    // When no provider is available, mainly because of custom-events, we use
-    // the underlying event listeners from the DOM.
-    var eventName = onEvent.substring(2).toLowerCase(); // onOneTwo => onetwo
-    // Most events names in Dart match those in JS in lowercase except for some
-    // few events listed in this map. We expect these cases to be handled above,
-    // but just in case we include them as a safety net here.
-    var jsNameFixes = const {
-      'animationend': 'webkitAnimationEnd',
-      'animationiteration': 'webkitAnimationIteration',
-      'animationstart': 'webkitAnimationStart',
-      'doubleclick': 'dblclick',
-      'fullscreenchange': 'webkitfullscreenchange',
-      'fullscreenerror': 'webkitfullscreenerror',
-      'keyadded': 'webkitkeyadded',
-      'keyerror': 'webkitkeyerror',
-      'keymessage': 'webkitkeymessage',
-      'needkey': 'webkitneedkey',
-      'speechchange': 'webkitSpeechChange',
-    };
-    var fixedName = jsNameFixes[eventName];
-    node.on[fixedName != null ? fixedName : eventName].listen(listener);
-  }
-
-  void _addInstanceListeners(ShadowRoot root, String elementName) {
-    var events = _templateDelegates[elementName];
-    if (events == null) return;
-    for (var eventName in events) {
-      _addNodeListener(root, eventName,
-          (e) => _instanceEventListener(eventName, e));
-    }
-  }
-
-  void _hostEventListener(String eventName, Event event) {
-    var method = _delegates[eventName];
-    if (event.bubbles && method != null) {
-      _dispatchMethod(this, method, event, host);
-    }
-  }
-
-  void _dispatchMethod(Object receiver, String methodName, Event event,
-      Node target) {
-    var detail = event is CustomEvent ? (event as CustomEvent).detail : null;
-    var args = [event, detail, target];
-
-    var method = new Symbol(methodName);
-    // TODO(sigmund): consider making event listeners list all arguments
-    // explicitly. Unless VM mirrors are optimized first, this reflectClass call
-    // will be expensive once custom elements extend directly from Element (see
-    // dartbug.com/11108).
-    var methodDecl = reflectClass(receiver.runtimeType).methods[method];
-    if (methodDecl != null) {
-      // This will either truncate the argument list or extend it with extra
-      // null arguments, so it will match the signature.
-      // TODO(sigmund): consider accepting optional arguments when we can tell
-      // them appart from named arguments (see http://dartbug.com/11334)
-      args.length = methodDecl.parameters.where((p) => !p.isOptional).length;
-    }
-    reflect(receiver).invoke(method, args);
-    performMicrotaskCheckpoint();
-  }
-
-  bool _instanceEventListener(String eventName, Event event) {
-    if (event.bubbles) {
-      if (event.path == null || !ShadowRoot.supported) {
-        return _listenLocalNoEventPath(eventName, event);
-      } else {
-        return _listenLocal(eventName, event);
-      }
-    }
-    return false;
-  }
-
-  bool _listenLocal(String eventName, Event event) {
-    var controller = null;
-    for (var target in event.path) {
-      // if we hit host, stop
-      if (target == host) return true;
-
-      // find a controller for the target, unless we already found `host`
-      // as a controller
-      controller = (controller == host) ? controller : _findController(target);
-
-      // if we have a controller, dispatch the event, and stop if the handler
-      // returns true
-      if (controller != null
-          && handleEvent(controller, eventName, event, target)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  // TODO(sorvell): remove when ShadowDOM polyfill supports event path.
-  // Note that _findController will not return the expected controller when the
-  // event target is a distributed node.  This is because we cannot traverse
-  // from a composed node to a node in shadowRoot.
-  // This will be addressed via an event path api
-  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066
-  bool _listenLocalNoEventPath(String eventName, Event event) {
-    var target = event.target;
-    var controller = null;
-    while (target != null && target != host) {
-      controller = (controller == host) ? controller : _findController(target);
-      if (controller != null
-          && handleEvent(controller, eventName, event, target)) {
-        return true;
-      }
-      target = target.parent;
-    }
-    return false;
-  }
-
-  // TODO(sigmund): investigate if this implementation is correct. Polymer looks
-  // up the shadow-root that contains [node] and uses a weak-hashmap to find the
-  // host associated with that root. This implementation assumes that the
-  // [node] is under [host]'s shadow-root.
-  Element _findController(Node node) => host.xtag;
-
-  bool handleEvent(
-      Element controller, String eventName, Event event, Element element) {
-    // Note: local events are listened only in the shadow root. This dynamic
-    // lookup is used to distinguish determine whether the target actually has a
-    // listener, and if so, to determine lazily what's the target method.
-    var methodName = element.attributes[toHyphenedName(eventName)];
-    if (methodName != null) {
-      _dispatchMethod(controller, methodName, event, element);
-    }
-    return event.bubbles;
-  }
-}
-
-
-/** Event stream providers per event name. */
-// TODO(sigmund): after dartbug.com/11108 is fixed, consider eliminating this
-// table and using reflection instead.
-const Map<String, EventStreamProvider> _eventStreamProviders = const {
-  'onMouseWheel': Element.mouseWheelEvent,
-  'onTransitionEnd': Element.transitionEndEvent,
-  'onAbort': Element.abortEvent,
-  'onBeforeCopy': Element.beforeCopyEvent,
-  'onBeforeCut': Element.beforeCutEvent,
-  'onBeforePaste': Element.beforePasteEvent,
-  'onBlur': Element.blurEvent,
-  'onChange': Element.changeEvent,
-  'onClick': Element.clickEvent,
-  'onContextMenu': Element.contextMenuEvent,
-  'onCopy': Element.copyEvent,
-  'onCut': Element.cutEvent,
-  'onDoubleClick': Element.doubleClickEvent,
-  'onDrag': Element.dragEvent,
-  'onDragEnd': Element.dragEndEvent,
-  'onDragEnter': Element.dragEnterEvent,
-  'onDragLeave': Element.dragLeaveEvent,
-  'onDragOver': Element.dragOverEvent,
-  'onDragStart': Element.dragStartEvent,
-  'onDrop': Element.dropEvent,
-  'onError': Element.errorEvent,
-  'onFocus': Element.focusEvent,
-  'onInput': Element.inputEvent,
-  'onInvalid': Element.invalidEvent,
-  'onKeyDown': Element.keyDownEvent,
-  'onKeyPress': Element.keyPressEvent,
-  'onKeyUp': Element.keyUpEvent,
-  'onLoad': Element.loadEvent,
-  'onMouseDown': Element.mouseDownEvent,
-  'onMouseMove': Element.mouseMoveEvent,
-  'onMouseOut': Element.mouseOutEvent,
-  'onMouseOver': Element.mouseOverEvent,
-  'onMouseUp': Element.mouseUpEvent,
-  'onPaste': Element.pasteEvent,
-  'onReset': Element.resetEvent,
-  'onScroll': Element.scrollEvent,
-  'onSearch': Element.searchEvent,
-  'onSelect': Element.selectEvent,
-  'onSelectStart': Element.selectStartEvent,
-  'onSubmit': Element.submitEvent,
-  'onTouchCancel': Element.touchCancelEvent,
-  'onTouchEnd': Element.touchEndEvent,
-  'onTouchEnter': Element.touchEnterEvent,
-  'onTouchLeave': Element.touchLeaveEvent,
-  'onTouchMove': Element.touchMoveEvent,
-  'onTouchStart': Element.touchStartEvent,
-  'onFullscreenChange': Element.fullscreenChangeEvent,
-  'onFullscreenError': Element.fullscreenErrorEvent,
-  'onAutocomplete': FormElement.autocompleteEvent,
-  'onAutocompleteError': FormElement.autocompleteErrorEvent,
-  'onSpeechChange': InputElement.speechChangeEvent,
-  'onCanPlay': MediaElement.canPlayEvent,
-  'onCanPlayThrough': MediaElement.canPlayThroughEvent,
-  'onDurationChange': MediaElement.durationChangeEvent,
-  'onEmptied': MediaElement.emptiedEvent,
-  'onEnded': MediaElement.endedEvent,
-  'onLoadStart': MediaElement.loadStartEvent,
-  'onLoadedData': MediaElement.loadedDataEvent,
-  'onLoadedMetadata': MediaElement.loadedMetadataEvent,
-  'onPause': MediaElement.pauseEvent,
-  'onPlay': MediaElement.playEvent,
-  'onPlaying': MediaElement.playingEvent,
-  'onProgress': MediaElement.progressEvent,
-  'onRateChange': MediaElement.rateChangeEvent,
-  'onSeeked': MediaElement.seekedEvent,
-  'onSeeking': MediaElement.seekingEvent,
-  'onShow': MediaElement.showEvent,
-  'onStalled': MediaElement.stalledEvent,
-  'onSuspend': MediaElement.suspendEvent,
-  'onTimeUpdate': MediaElement.timeUpdateEvent,
-  'onVolumeChange': MediaElement.volumeChangeEvent,
-  'onWaiting': MediaElement.waitingEvent,
-  'onKeyAdded': MediaElement.keyAddedEvent,
-  'onKeyError': MediaElement.keyErrorEvent,
-  'onKeyMessage': MediaElement.keyMessageEvent,
-  'onNeedKey': MediaElement.needKeyEvent,
-  'onWebGlContextLost': CanvasElement.webGlContextLostEvent,
-  'onWebGlContextRestored': CanvasElement.webGlContextRestoredEvent,
-  'onPointerLockChange': Document.pointerLockChangeEvent,
-  'onPointerLockError': Document.pointerLockErrorEvent,
-  'onReadyStateChange': Document.readyStateChangeEvent,
-  'onSelectionChange': Document.selectionChangeEvent,
-  'onSecurityPolicyViolation': Document.securityPolicyViolationEvent,
-};
+export 'polymer.dart' show PolymerElement, registerPolymerElement;
diff --git a/pkg/polymer/lib/src/build/linter.dart b/pkg/polymer/lib/src/build/linter.dart
index 3ed9c50..6542df7 100644
--- a/pkg/polymer/lib/src/build/linter.dart
+++ b/pkg/polymer/lib/src/build/linter.dart
@@ -16,8 +16,10 @@
 import 'package:barback/barback.dart';
 import 'package:html5lib/dom.dart';
 import 'package:html5lib/dom_parsing.dart';
+import 'package:source_maps/span.dart';
 
 import 'common.dart';
+import 'utils.dart';
 
 typedef String MessageFormatter(String kind, String message, Span span);
 
@@ -191,6 +193,9 @@
 /**
  * Information needed about other polymer-element tags in order to validate
  * how they are used and extended.
+ *
+ * Note: these are only created for polymer-element, because pure custom
+ * elements don't have a declarative form.
  */
 class _ElementSummary {
   final String tagName;
@@ -284,6 +289,19 @@
           node.sourceSpan);
     }
 
+    var attrs = node.attributes['attributes'];
+    if (attrs != null) {
+      var attrsSpan = node.attributeSpans['attributes'];
+
+      // names='a b c' or names='a,b,c'
+      // record each name for publishing
+      for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) {
+        // remove excess ws
+        attr = attr.trim();
+        if (!_validateCustomAttributeName(attr, attrsSpan)) break;
+      }
+    }
+
     var oldValue = _inPolymerElement;
     _inPolymerElement = true;
     super.visitElement(node);
@@ -369,10 +387,13 @@
 
     var info = _elements[customTagName];
     if (info == null) {
-      _logger.warning('definition for custom element with tag name '
+      // TODO(jmesserly): this warning is wrong if someone is using raw custom
+      // elements. Is there another way we can handle this warning that won't
+      // generate false positives?
+      _logger.warning('definition for Polymer element with tag name '
           '"$customTagName" not found.', node.sourceSpan);
       return;
-    } 
+    }
 
     var baseTag = info.baseExtendsTag;
     if (baseTag != null && !hasIsAttribute) {
@@ -384,7 +405,7 @@
           'the custom element declaration.', node.sourceSpan);
       return;
     }
-    
+
     if (hasIsAttribute && baseTag == null) {
       _logger.warning(
           'custom element "$customTagName" doesn\'t declare any type '
@@ -393,7 +414,7 @@
           'the custom element declaration.', node.sourceSpan);
       return;
     }
-    
+
     if (hasIsAttribute && baseTag != nodeTag) {
       _logger.warning(
           'custom element "$customTagName" extends from "$baseTag". '
@@ -402,6 +423,20 @@
     }
   }
 
+  /**
+   * Validate an attribute on a custom-element. Returns true if valid.
+   */
+  bool _validateCustomAttributeName(String name, FileSpan span) {
+    if (name.contains('-')) {
+      var newName = toCamelCase(name);
+      _logger.warning('PolymerElement no longer recognizes attribute names with '
+          'dashes such as "$name". Use "$newName" or "${newName.toLowerCase()}" '
+          'instead (both forms are equivalent in HTML).', span);
+      return false;
+    }
+    return true;
+  }
+
   /** Validate event handlers are used correctly. */
   void _validateEventHandler(Element node, String name, String value) {
     if (!name.startsWith('on-')) {
@@ -409,20 +444,29 @@
           ' JavaScript event handler. Use the form '
           'on-event-name="handlerName" if you want a Dart handler '
           'that will automatically update the UI based on model changes.',
-          node.sourceSpan);
+          node.attributeSpans[name]);
       return;
     }
 
     if (!_inPolymerElement) {
       _logger.warning('Inline event handlers are only supported inside '
-          'declarations of <polymer-element>.', node.sourceSpan);
+          'declarations of <polymer-element>.', node.attributeSpans[name]);
+    }
+
+    var eventName = name.substring('on-'.length);
+    if (eventName.contains('-')) {
+      var newEvent = toCamelCase(eventName);
+      _logger.warning('Invalid event name "$name". After the "on-" the event '
+          'name should not use dashes. For example use "on-$newEvent" or '
+          '"on-${newEvent.toLowerCase()}" (both forms are equivalent in HTML).',
+          node.attributeSpans[name]);
     }
 
     if (value.contains('.') || value.contains('(')) {
       _logger.warning('Invalid event handler body "$value". Declare a method '
           'in your custom element "void handlerName(event, detail, target)" '
           'and use the form $name="handlerName".',
-          node.sourceSpan);
+          node.attributeSpans[name]);
     }
   }
 }
diff --git a/pkg/polymer/lib/src/build/runner.dart b/pkg/polymer/lib/src/build/runner.dart
index d940c18..3596e92 100644
--- a/pkg/polymer/lib/src/build/runner.dart
+++ b/pkg/polymer/lib/src/build/runner.dart
@@ -105,7 +105,7 @@
 final Set<String> _polymerPackageDependencies = [
     'analyzer_experimental', 'args', 'barback', 'browser', 'csslib',
     'custom_element', 'fancy_syntax', 'html5lib', 'html_import', 'js',
-    'logging', 'mdv', 'meta', 'mutation_observer', 'observe', 'path', 'polymer',
+    'logging', 'mdv', 'meta', 'mutation_observer', 'observe', 'path'
     'polymer_expressions', 'serialization', 'shadow_dom', 'source_maps',
     'stack_trace', 'unittest', 'unmodifiable_collection', 'yaml'].toSet();
 
@@ -149,7 +149,9 @@
   }
 
   for (var package in options.packageDirs.keys) {
-    // There is nothing to do in the 'polymer' package and its dependencies.
+    // There is nothing to do in the polymer package dependencies.
+    // However: in Polymer package *itself*, we need to replace ObservableMixin
+    // with ChangeNotifierMixin.
     if (!options.transformPolymerDependencies &&
         _polymerPackageDependencies.contains(package)) continue;
     barback.updateTransformers(package, options.phases);
diff --git a/pkg/polymer/lib/src/utils.dart b/pkg/polymer/lib/src/build/utils.dart
similarity index 100%
rename from pkg/polymer/lib/src/utils.dart
rename to pkg/polymer/lib/src/build/utils.dart
diff --git a/pkg/polymer/lib/src/declaration.dart b/pkg/polymer/lib/src/declaration.dart
new file mode 100644
index 0000000..a7584b6
--- /dev/null
+++ b/pkg/polymer/lib/src/declaration.dart
@@ -0,0 +1,713 @@
+// 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 polymer;
+
+/**
+ * **Deprecated**: use [Polymer.register] instead.
+ *
+ * Registers a [PolymerElement]. This is similar to [registerCustomElement]
+ * but it is designed to work with the `<element>` element and adds additional
+ * features.
+ */
+@deprecated
+void registerPolymerElement(String localName, PolymerElement create()) {
+  Polymer._registerClassMirror(localName, reflect(create()).type);
+}
+
+/**
+ * **Warning**: this class is experiental and subject to change.
+ *
+ * The implementation for the `polymer-element` element.
+ *
+ * Normally you do not need to use this class directly, see [PolymerElement].
+ */
+class PolymerDeclaration extends CustomElement {
+  // Fully ported from revision:
+  // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f21267779
+  //
+  //   src/declaration/attributes.js
+  //   src/declaration/events.js
+  //   src/declaration/polymer-element.js
+  //   src/declaration/properties.js
+  //   src/declaration/prototype.js (note: most code not needed in Dart)
+  //   src/declaration/styles.js
+  //
+  // Not yet ported:
+  //   src/declaration/path.js - blocked on HTMLImports.getDocumentUrl
+
+  // TODO(jmesserly): these should be Type not ClassMirror. But we can't get
+  // from ClassMirror to Type yet in dart2js, so we use ClassMirror for now.
+  // See https://code.google.com/p/dart/issues/detail?id=12607
+  ClassMirror _type;
+  ClassMirror get type => _type;
+
+  // TODO(jmesserly): this is a cache, because it's tricky in Dart to get from
+  // ClassMirror -> Supertype.
+  ClassMirror _supertype;
+  ClassMirror get supertype => _supertype;
+
+  // TODO(jmesserly): this is also a cache, since we can't store .element on
+  // each level of the __proto__ like JS does.
+  PolymerDeclaration _super;
+  PolymerDeclaration get superDeclaration => _super;
+
+  String _name;
+  String get name => _name;
+
+  /**
+   * Map of publish properties. Can be a [VariableMirror] or a [MethodMirror]
+   * representing a getter. If it is a getter, there will also be a setter.
+   */
+  Map<String, DeclarationMirror> _publish;
+
+  /** The names of published properties for this polymer-element. */
+  Iterable<String> get publishedProperties =>
+      _publish != null ? _publish.keys : const [];
+
+  /** Same as [_publish] but with lower case names. */
+  Map<String, DeclarationMirror> _publishLC;
+
+  Map<String, Symbol> _observe;
+
+  Map<Symbol, Object> _instanceAttributes;
+
+  List<Element> _sheets;
+  List<Element> get sheets => _sheets;
+
+  List<Element> _styles;
+  List<Element> get styles => _styles;
+
+  DocumentFragment get templateContent {
+    final template = query('template');
+    return template != null ? template.content : null;
+  }
+
+  /** Maps event names and their associated method in the element class. */
+  final Map<String, String> _eventDelegates = {};
+
+  /** Expected events per element node. */
+  // TODO(sigmund): investigate whether we need more than 1 set of local events
+  // per element (why does the js implementation stores 1 per template node?)
+  Expando<Set<String>> _templateDelegates;
+
+  void created() {
+    super.created();
+
+    // fetch the element name
+    _name = attributes['name'];
+    // install element definition, if ready
+    registerWhenReady();
+  }
+
+  void registerWhenReady() {
+    // if we have no prototype, wait
+    if (waitingForType(name)) {
+      return;
+    }
+    // fetch our extendee name
+    var extendee = attributes['extends'];
+    if (waitingForExtendee(extendee)) {
+      //console.warn(name + ': waitingForExtendee:' + extendee);
+      return;
+    }
+    // TODO(sjmiles): HTMLImports polyfill awareness:
+    // elements in the main document are likely to parse
+    // in advance of elements in imports because the
+    // polyfill parser is simulated
+    // therefore, wait for imports loaded before
+    // finalizing elements in the main document
+    // TODO(jmesserly): Polymer.dart waits for HTMLImportsLoaded, so I've
+    // removed "whenImportsLoaded" for now. Restore the workaround if needed.
+    _register(extendee);
+  }
+
+  void _register(extendee) {
+    //console.group('registering', name);
+    register(name, extendee);
+    //console.groupEnd();
+    // subclasses may now register themselves
+    _notifySuper(name);
+  }
+
+  bool waitingForType(String name) {
+    if (_getRegisteredType(name) != null) return false;
+
+    // then wait for a prototype
+    _waitType[name] = this;
+    // if explicitly marked as 'noscript'
+    if (attributes.containsKey('noscript')) {
+      // TODO(sorvell): CustomElements polyfill awareness:
+      // noscript elements should upgrade in logical order
+      // script injection ensures this under native custom elements;
+      // under imports + ce polyfills, scripts run before upgrades.
+      // dependencies should be ready at upgrade time so register
+      // prototype at this time.
+      // TODO(jmesserly): I'm not sure how to port this; since script
+      // injection doesn't work for Dart, we'll just call Polymer.register
+      // here and hope for the best.
+      Polymer.register(name);
+    }
+    return true;
+  }
+
+  bool waitingForExtendee(String extendee) {
+    // if extending a custom element...
+    if (extendee != null && extendee.indexOf('-') >= 0) {
+      // wait for the extendee to be _registered first
+      if (!_isRegistered(extendee)) {
+        _waitSuper.putIfAbsent(extendee, () => []).add(this);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void register(String name, String extendee) {
+    // build prototype combining extendee, Polymer base, and named api
+    buildType(name, extendee);
+
+    // back reference declaration element
+    // TODO(sjmiles): replace `element` with `elementElement` or `declaration`
+    _declarations[_type] = this;
+
+    // more declarative features
+    desugar();
+
+    // TODO(sorvell): install a helper method this.resolvePath to aid in
+    // setting resource paths. e.g.
+    // this.$.image.src = this.resolvePath('images/foo.png')
+    // Potentially remove when spec bug is addressed.
+    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407
+    // TODO(jmesserly): resolvePath not ported, see first comment in this class.
+
+    // under ShadowDOMPolyfill, transforms to approximate missing CSS features
+    _shimShadowDomStyling(templateContent, name);
+
+    // register our custom element
+    registerType(name);
+
+    // NOTE: skip in Dart because we don't have mutable global scope.
+    // reference constructor in a global named by 'constructor' attribute
+    // publishConstructor();
+  }
+
+  /**
+   * Gets the Dart type registered for this name, and sets up declarative
+   * features. Fills in the [type] and [supertype] fields.
+   *
+   * *Note*: unlike the JavaScript version, we do not have to metaprogram the
+   * prototype, which simplifies this method.
+   */
+  void buildType(String name, String extendee) {
+    // get our custom type
+    _type = _getRegisteredType(name);
+
+    // get basal prototype
+    _supertype = _getRegisteredType(extendee);
+    if (supertype != null) _super = _getDeclaration(supertype);
+
+    // transcribe `attributes` declarations onto own prototype's `publish`
+    publishAttributes(type, _super);
+
+    publishProperties(type);
+
+    inferObservers(type);
+
+    // Skip the rest in Dart:
+    // chain various meta-data objects to inherited versions
+    // chain custom api to inherited
+    // build side-chained lists to optimize iterations
+    // inherit publishing meta-data
+    //this.inheritAttributesObjects(prototype);
+    //this.inheritDelegates(prototype);
+    // x-platform fixups
+  }
+
+  /** Implement various declarative features. */
+  void desugar() {
+    // compile list of attributes to copy to instances
+    accumulateInstanceAttributes();
+    // parse on-* delegates declared on `this` element
+    parseHostEvents();
+    // parse on-* delegates declared in templates
+    parseLocalEvents();
+    // install external stylesheets as if they are inline
+    installSheets();
+    // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient
+    // lazy static initialization, can we get by without it?
+    var registered = type.methods[const Symbol('registerCallback')];
+    if (registered != null && registered.isStatic &&
+        registered.isRegularMethod) {
+      type.invoke(const Symbol('registerCallback'), [this]);
+    }
+
+  }
+
+  void registerType(String name) {
+    // TODO(jmesserly): document.register
+    registerCustomElement(name, () =>
+        type.newInstance(const Symbol(''), const []).reflectee);
+  }
+
+  void publishAttributes(ClassMirror type, PolymerDeclaration superDecl) {
+    // get properties to publish
+    if (superDecl != null && superDecl._publish != null) {
+      _publish = new Map.from(superDecl._publish);
+    }
+    _publish = _getProperties(type, _publish, (x) => x is PublishedProperty);
+
+    // merge names from 'attributes' attribute
+    var attrs = attributes['attributes'];
+    if (attrs != null) {
+      // names='a b c' or names='a,b,c'
+      // record each name for publishing
+      for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) {
+        // remove excess ws
+        attr = attr.trim();
+
+        // do not override explicit entries
+        if (_publish != null && _publish.containsKey(attr)) continue;
+
+        var property = new Symbol(attr);
+        var mirror = type.variables[property];
+        if (mirror == null) {
+          mirror = type.getters[property];
+          if (mirror != null && !_hasSetter(type, mirror)) mirror = null;
+        }
+        if (mirror == null) {
+          window.console.warn('property for attribute $attr of polymer-element '
+              'name=$name not found.');
+          continue;
+        }
+        if (_publish == null) _publish = {};
+        _publish[attr] = mirror;
+      }
+    }
+
+    // NOTE: the following is not possible in Dart; fields must be declared.
+    // install 'attributes' as properties on the prototype,
+    // but don't override
+  }
+
+  void accumulateInstanceAttributes() {
+    // inherit instance attributes
+    _instanceAttributes = new Map<Symbol, Object>();
+    if (_super != null) _instanceAttributes.addAll(_super._instanceAttributes);
+
+    // merge attributes from element
+    attributes.forEach((name, value) {
+      if (isInstanceAttribute(name)) {
+        _instanceAttributes[new Symbol(name)] = value;
+      }
+    });
+  }
+
+  static bool isInstanceAttribute(name) {
+    // do not clone these attributes onto instances
+    final blackList = const {
+        'name': 1, 'extends': 1, 'constructor': 1, 'noscript': 1,
+        'attributes': 1};
+
+    return !blackList.containsKey(name) && !name.startsWith('on-');
+  }
+
+  /** Extracts events from the element tag attributes. */
+  void parseHostEvents() {
+    addAttributeDelegates(_eventDelegates);
+  }
+
+  void addAttributeDelegates(Map<String, String> delegates) {
+    attributes.forEach((name, value) {
+      if (_hasEventPrefix(name)) {
+        delegates[_removeEventPrefix(name)] = value;
+      }
+    });
+  }
+
+  /** Extracts events under the element's <template>. */
+  void parseLocalEvents() {
+    for (var t in queryAll('template')) {
+      final events = new Set<String>();
+      // acquire delegates from entire subtree at t
+      accumulateTemplatedEvents(t, events);
+      if (events.isNotEmpty) {
+        // store delegate information directly on template
+        if (_templateDelegates == null) {
+          _templateDelegates = new Expando<Set<String>>();
+        }
+        _templateDelegates[t] = events;
+      }
+    }
+  }
+
+  void accumulateTemplatedEvents(Element node, Set<String> events) {
+    if (node.localName == 'template' && node.content != null) {
+      accumulateChildEvents(node.content, events);
+    }
+  }
+
+  void accumulateChildEvents(node, Set<String> events) {
+    assert(node is Element || node is DocumentFragment);
+    for (var n in node.children) {
+      accumulateEvents(n, events);
+    }
+  }
+
+  void accumulateEvents(Element node, Set<String> events) {
+    accumulateAttributeEvents(node, events);
+    accumulateChildEvents(node, events);
+    accumulateTemplatedEvents(node, events);
+  }
+
+  void accumulateAttributeEvents(Element node, Set<String> events) {
+    for (var name in node.attributes.keys) {
+      if (_hasEventPrefix(name)) {
+        accumulateEvent(_removeEventPrefix(name), events);
+      }
+    }
+  }
+
+  void accumulateEvent(String name, Set<String> events) {
+    var translated = _eventTranslations[name];
+    events.add(translated != null ? translated : name);
+  }
+
+  String urlToPath(String url) {
+    if (url == null) return '';
+    return (url.split('/')..removeLast()..add('')).join('/');
+  }
+
+  /**
+   * Install external stylesheets loaded in <element> elements into the
+   * element's template.
+   */
+  void installSheets() {
+    cacheSheets();
+    cacheStyles();
+    installLocalSheets();
+    installGlobalStyles();
+  }
+
+  void cacheSheets() {
+    _sheets = findNodes(_SHEET_SELECTOR);
+    for (var s in sheets) s.remove();
+  }
+
+  void cacheStyles() {
+    _styles = findNodes('$_STYLE_SELECTOR[$_SCOPE_ATTR]');
+    for (var s in styles) s.remove();
+  }
+
+  /**
+   * Takes external stylesheets loaded in an `<element>` element and moves
+   * their content into a style element inside the `<element>`'s template.
+   * The sheet is then removed from the `<element>`. This is done only so
+   * that if the element is loaded in the main document, the sheet does
+   * not become active.
+   * Note, ignores sheets with the attribute 'polymer-scope'.
+   */
+  void installLocalSheets() {
+    var sheets = this.sheets.where(
+        (s) => !s.attributes.containsKey(_SCOPE_ATTR));
+    var content = this.templateContent;
+    if (content != null) {
+      var cssText = new StringBuffer();
+      for (var sheet in sheets) {
+        cssText..write(_cssTextFromSheet(sheet))..write('\n');
+      }
+      if (cssText.length > 0) {
+        content.insertBefore(
+            new StyleElement()..text = '$cssText',
+            content.firstChild);
+      }
+    }
+  }
+
+  List<Element> findNodes(String selector, [bool matcher(Element e)]) {
+    var nodes = this.queryAll(selector).toList();
+    var content = this.templateContent;
+    if (content != null) {
+      nodes = nodes..addAll(content.queryAll(selector));
+    }
+    if (matcher != null) return nodes.where(matcher).toList();
+    return nodes;
+  }
+
+  /**
+   * Promotes external stylesheets and style elements with the attribute
+   * polymer-scope='global' into global scope.
+   * This is particularly useful for defining @keyframe rules which
+   * currently do not function in scoped or shadow style elements.
+   * (See wkb.ug/72462)
+   */
+  // TODO(sorvell): remove when wkb.ug/72462 is addressed.
+  void installGlobalStyles() {
+    var style = styleForScope(_STYLE_GLOBAL_SCOPE);
+    _applyStyleToScope(style, document.head);
+  }
+
+  String cssTextForScope(String scopeDescriptor) {
+    var cssText = new StringBuffer();
+    // handle stylesheets
+    var selector = '[$_SCOPE_ATTR=$scopeDescriptor]';
+    matcher(s) => s.matches(selector);
+
+    for (var sheet in sheets.where(matcher)) {
+      cssText..write(_cssTextFromSheet(sheet))..write('\n\n');
+    }
+    // handle cached style elements
+    for (var style in styles.where(matcher)) {
+      cssText..write(style.textContent)..write('\n\n');
+    }
+    return cssText.toString();
+  }
+
+  StyleElement styleForScope(String scopeDescriptor) {
+    var cssText = cssTextForScope(scopeDescriptor);
+    return cssTextToScopeStyle(cssText, scopeDescriptor);
+  }
+
+  StyleElement cssTextToScopeStyle(String cssText, String scopeDescriptor) {
+    if (cssText == '') return null;
+
+    return new StyleElement()
+        ..text = cssText
+        ..attributes[_STYLE_SCOPE_ATTRIBUTE] = '$name-$scopeDescriptor';
+  }
+
+  /**
+   * fetch a list of all observable properties names in our inheritance chain
+   * above Polymer.
+   */
+  // TODO(sjmiles): perf: reflection is slow, relatively speaking
+  // If an element may take 6us to create, getCustomPropertyNames might
+  // cost 1.6us more.
+  void inferObservers(ClassMirror type) {
+    for (var method in type.methods.values) {
+      if (method.isStatic || !method.isRegularMethod) continue;
+
+      String name = MirrorSystem.getName(method.simpleName);
+      if (name.endsWith('Changed')) {
+        if (_observe == null) _observe = {};
+        name = name.substring(0, name.length - 7);
+        _observe[name] = method.simpleName;
+      }
+    }
+  }
+
+  void publishProperties(ClassMirror type) {
+    // Dart note: _publish was already populated by publishAttributes
+    if (_publish != null) _publishLC = _lowerCaseMap(_publish);
+  }
+
+  Map<String, dynamic> _lowerCaseMap(Map<String, dynamic> properties) {
+    final map = new Map<String, dynamic>();
+    properties.forEach((name, value) {
+      map[name.toLowerCase()] = value;
+    });
+    return map;
+  }
+}
+
+/// maps tag names to prototypes
+final Map _typesByName = new Map<String, ClassMirror>();
+
+ClassMirror _getRegisteredType(String name) => _typesByName[name];
+
+/// elements waiting for prototype, by name
+final Map _waitType = new Map<String, PolymerDeclaration>();
+
+void _notifyType(String name) {
+  var waiting = _waitType.remove(name);
+  if (waiting != null) waiting.registerWhenReady();
+}
+
+/// elements waiting for super, by name
+final Map _waitSuper = new Map<String, List<PolymerDeclaration>>();
+
+void _notifySuper(String name) {
+  _registered.add(name);
+  var waiting = _waitSuper.remove(name);
+  if (waiting != null) {
+    for (var w in waiting) {
+      w.registerWhenReady();
+    }
+  }
+}
+
+/// track document.register'ed tag names
+final Set _registered = new Set<String>();
+
+bool _isRegistered(name) => _registered.contains(name);
+
+final Map _declarations = new Map<ClassMirror, PolymerDeclaration>();
+
+PolymerDeclaration _getDeclaration(ClassMirror type) => _declarations[type];
+
+final _objectType = reflectClass(Object);
+
+Map _getProperties(ClassMirror type, Map props, bool matches(metadata)) {
+  for (var field in type.variables.values) {
+    if (field.isFinal || field.isStatic || field.isPrivate) continue;
+
+    for (var meta in field.metadata) {
+      if (matches(meta.reflectee)) {
+        if (props == null) props = {};
+        props[MirrorSystem.getName(field.simpleName)] = field;
+        break;
+      }
+    }
+  }
+
+  for (var getter in type.getters.values) {
+    if (getter.isStatic || getter.isPrivate) continue;
+
+    for (var meta in getter.metadata) {
+      if (matches(meta.reflectee)) {
+        if (_hasSetter(type, getter)) {
+          if (props == null) props = {};
+          props[MirrorSystem.getName(getter.simpleName)] = getter;
+        }
+        break;
+      }
+    }
+  }
+
+  return props;
+}
+
+bool _hasSetter(ClassMirror type, MethodMirror getter) {
+  var setterName = new Symbol('${MirrorSystem.getName(getter.simpleName)}=');
+  return type.setters.containsKey(setterName);
+}
+
+bool _inDartHtml(ClassMirror type) =>
+    type.owner.simpleName == const Symbol('dart.dom.html');
+
+
+/** Attribute prefix used for declarative event handlers. */
+const _EVENT_PREFIX = 'on-';
+
+/** Whether an attribute declares an event. */
+bool _hasEventPrefix(String attr) => attr.startsWith(_EVENT_PREFIX);
+
+String _removeEventPrefix(String name) => name.substring(_EVENT_PREFIX.length);
+
+/**
+ * Using Polymer's platform/src/ShadowCSS.js passing the style tag's content.
+ */
+void _shimShadowDomStyling(DocumentFragment template, String localName) {
+  if (js.context == null || template == null) return;
+
+  var platform = js.context['Platform'];
+  if (platform == null) return;
+
+  var style = template.query('style');
+  if (style == null) return;
+
+  var shadowCss = platform['ShadowCSS'];
+  if (shadowCss == null) return;
+
+  // TODO(terry): Remove calls to shimShadowDOMStyling2 and replace with
+  //              shimShadowDOMStyling when we support unwrapping dart:html
+  //              Element to a JS DOM node.
+  var shimShadowDOMStyling2 = shadowCss['shimShadowDOMStyling2'];
+  if (shimShadowDOMStyling2 == null) return;
+
+  var scopedCSS = shimShadowDOMStyling2.apply(shadowCss,
+      [style.text, localName]);
+
+  // TODO(terry): Remove when shimShadowDOMStyling is called we don't need to
+  //              replace original CSS with scoped CSS shimShadowDOMStyling
+  //              does that.
+  style.text = scopedCSS;
+}
+
+const _STYLE_SELECTOR = 'style';
+const _SHEET_SELECTOR = '[rel=stylesheet]';
+const _STYLE_GLOBAL_SCOPE = 'global';
+const _SCOPE_ATTR = 'polymer-scope';
+const _STYLE_SCOPE_ATTRIBUTE = 'element';
+
+void _applyStyleToScope(StyleElement style, Node scope) {
+  if (style == null) return;
+
+  // TODO(sorvell): necessary for IE
+  // see https://connect.microsoft.com/IE/feedback/details/790212/
+  // cloning-a-style-element-and-adding-to-document-produces
+  // -unexpected-result#details
+  // var clone = style.cloneNode(true);
+  var clone = new StyleElement()..text = style.text;
+
+  var attr = style.attributes[_STYLE_SCOPE_ATTRIBUTE];
+  if (attr != null) {
+    clone.attributes[_STYLE_SCOPE_ATTRIBUTE] = attr;
+  }
+
+  scope.append(clone);
+}
+
+String _cssTextFromSheet(Element sheet) {
+  if (sheet == null || js.context == null) return '';
+
+  // TODO(jmesserly): this is a hacky way to communcate with HTMLImports...
+
+  // Remove rel=stylesheet, href to keep this inert.
+  var href = sheet.attributes.remove('href');
+  var rel = sheet.attributes.remove('rel');
+  document.body.append(sheet);
+  String resource;
+  try {
+    resource = js.context['document']['body']['lastChild']['__resource'];
+  } finally {
+    sheet.remove();
+    if (href != null) sheet.attributes['href'] = href;
+    if (rel != null) sheet.attributes['rel'] = rel;
+  }
+  return resource != null ? resource : '';
+}
+
+const _OBSERVE_SUFFIX = 'Changed';
+
+// TODO(jmesserly): is this list complete?
+final _eventTranslations = const {
+  // TODO(jmesserly): these three Polymer.js translations won't work in Dart,
+  // because we strip the webkit prefix (below). Reconcile.
+  'webkitanimationstart': 'webkitAnimationStart',
+  'webkitanimationend': 'webkitAnimationEnd',
+  'webkittransitionend': 'webkitTransitionEnd',
+
+  'domfocusout': 'DOMFocusOut',
+  'domfocusin': 'DOMFocusIn',
+
+  // TODO(jmesserly): Dart specific renames. Reconcile with Polymer.js
+  'animationend': 'webkitAnimationEnd',
+  'animationiteration': 'webkitAnimationIteration',
+  'animationstart': 'webkitAnimationStart',
+  'doubleclick': 'dblclick',
+  'fullscreenchange': 'webkitfullscreenchange',
+  'fullscreenerror': 'webkitfullscreenerror',
+  'keyadded': 'webkitkeyadded',
+  'keyerror': 'webkitkeyerror',
+  'keymessage': 'webkitkeymessage',
+  'needkey': 'webkitneedkey',
+  'speechchange': 'webkitSpeechChange',
+};
+
+final _reverseEventTranslations = () {
+  final map = new Map<String, String>();
+  _eventTranslations.forEach((onName, eventType) {
+    map[eventType] = onName;
+  });
+  return map;
+}();
+
+// Dart note: we need this function because we have additional renames JS does
+// not have. The JS renames are simply case differences, whereas we have ones
+// like doubleclick -> dblclick and stripping the webkit prefix.
+String _eventNameFromType(String eventType) {
+  final result = _reverseEventTranslations[eventType];
+  return result != null ? result : eventType;
+}
diff --git a/pkg/polymer/lib/src/instance.dart b/pkg/polymer/lib/src/instance.dart
new file mode 100644
index 0000000..f0bff99
--- /dev/null
+++ b/pkg/polymer/lib/src/instance.dart
@@ -0,0 +1,930 @@
+// 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 polymer;
+
+/**
+ * Use this annotation to publish a field as an attribute. For example:
+ *
+ *     class MyPlaybackElement extends PolymerElement {
+ *       // This will be available as an HTML attribute, for example:
+ *       //     <my-playback volume="11">
+ *       @published double volume;
+ *     }
+ */
+// TODO(jmesserly): does @published imply @observable or vice versa?
+const published = const PublishedProperty();
+
+/** An annotation used to publish a field as an attribute. See [published]. */
+class PublishedProperty extends ObservableProperty {
+  const PublishedProperty();
+}
+
+// TODO(jmesserly): make this the mixin so we can have Polymer type extensions,
+// and move the implementation of PolymerElement in here. Once done it will look
+// like:
+// abstract class Polymer { ... all the things ... }
+// typedef PolymerElement = HtmlElement with Polymer, Observable;
+abstract class Polymer {
+  // TODO(jmesserly): should this really be public?
+  /** Regular expression that matches data-bindings. */
+  static final bindPattern = new RegExp(r'\{\{([^{}]*)}}');
+
+  /**
+   * Like [document.register] but for Polymer elements.
+   *
+   * Use the [name] to specify custom elment's tag name, for example:
+   * "fancy-button" if the tag is used as `<fancy-button>`.
+   *
+   * The [type] is the type to construct. If not supplied, it defaults to
+   * [PolymerElement].
+   */
+  // NOTE: this is called "element" in src/declaration/polymer-element.js, and
+  // exported as "Polymer".
+  static void register(String name, [Type type]) {
+    //console.log('registering [' + name + ']');
+    if (type == null) type = PolymerElement;
+    _registerClassMirror(name, reflectClass(type));
+  }
+
+  // TODO(jmesserly): we use ClassMirror internall for now, until it is possible
+  // to get from ClassMirror -> Type.
+  static void _registerClassMirror(String name, ClassMirror type) {
+    _typesByName[name] = type;
+    // notify the registrar waiting for 'name', if any
+    _notifyType(name);
+  }
+}
+
+/**
+ * The base class for Polymer elements. It provides convience features on top
+ * of the custom elements web standard.
+ */
+class PolymerElement extends CustomElement with ObservableMixin {
+  // Fully ported from revision:
+  // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f21267779
+  //
+  //   src/instance/attributes.js
+  //   src/instance/base.js
+  //   src/instance/events.js
+  //   src/instance/mdv.js
+  //   src/instance/properties.js
+  //   src/instance/utils.js
+  //
+  // Not yet ported:
+  //   src/instance/style.js -- blocked on ShadowCSS.shimPolyfillDirectives
+
+  /// The one syntax to rule them all.
+  static final BindingDelegate _polymerSyntax = new PolymerExpressions();
+
+  static int _preparingElements = 0;
+
+  PolymerDeclaration _declaration;
+
+  /** The most derived `<polymer-element>` declaration for this element. */
+  PolymerDeclaration get declaration => _declaration;
+
+  Map<String, StreamSubscription> _elementObservers;
+  bool _unbound; // lazy-initialized
+  Job _unbindAllJob;
+
+  bool get _elementPrepared => _declaration != null;
+
+  bool get applyAuthorStyles => false;
+  bool get resetStyleInheritance => false;
+  bool get alwaysPrepare => false;
+
+  /**
+   * Shadow roots created by [parseElement]. See [getShadowRoot].
+   */
+  final _shadowRoots = new HashMap<String, ShadowRoot>();
+
+  /** Map of items in the shadow root(s) by their [Element.id]. */
+  // TODO(jmesserly): various issues:
+  // * wrap in UnmodifiableMapView?
+  // * should we have an object that implements noSuchMethod?
+  // * should the map have a key order (e.g. LinkedHash or SplayTree)?
+  // * should this be a live list? Polymer doesn't, maybe due to JS limitations?
+  // For now I picked the most performant choice: non-live HashMap.
+  final Map<String, Element> $ = new HashMap<String, Element>();
+
+  /**
+   * Gets the shadow root associated with the corresponding custom element.
+   *
+   * This is identical to [shadowRoot], unless there are multiple levels of
+   * inheritance and they each have their own shadow root. For example,
+   * this can happen if the base class and subclass both have `<template>` tags
+   * in their `<polymer-element>` tags.
+   */
+  // TODO(jmesserly): Polymer does not have this feature. Reconcile.
+  ShadowRoot getShadowRoot(String customTagName) => _shadowRoots[customTagName];
+
+  ShadowRoot createShadowRoot([name]) {
+    if (name != null) {
+      throw new ArgumentError('name argument must not be supplied.');
+    }
+
+    // Provides ability to traverse from ShadowRoot to the host.
+    // TODO(jmessery): remove once we have this ability on the DOM.
+    final root = super.createShadowRoot();
+    _shadowHost[root] = host;
+    return root;
+  }
+
+  /**
+   * Invoke [callback] in [wait], unless the job is re-registered,
+   * which resets the timer. For example:
+   *
+   *     _myJob = job(_myJob, callback, const Duration(milliseconds: 100));
+   *
+   * Returns a job handle which can be used to re-register a job.
+   */
+  Job job(Job job, void callback(), Duration wait) =>
+      runJob(job, callback, wait);
+
+  // TODO(jmesserly): I am not sure if we should have the
+  // created/createdCallback distinction. See post here:
+  // https://groups.google.com/d/msg/polymer-dev/W0ZUpU5caIM/v5itFnvnehEJ
+  // Same issue with inserted and removed.
+  void created() {
+    if (document.window != null || alwaysPrepare || _preparingElements > 0) {
+      prepareElement();
+    }
+  }
+
+  void prepareElement() {
+    // Dart note: get the _declaration, which also marks _elementPrepared
+    _declaration = _getDeclaration(reflect(this).type);
+    // do this first so we can observe changes during initialization
+    observeProperties();
+    // install boilerplate attributes
+    copyInstanceAttributes();
+    // process input attributes
+    takeAttributes();
+    // add event listeners
+    addHostListeners();
+    // guarantees that while preparing, any sub-elements will also be prepared
+    _preparingElements++;
+    // process declarative resources
+    parseDeclarations(_declaration);
+    _preparingElements--;
+    // user entry point
+    ready();
+  }
+
+  /** Called when [prepareElement] is finished. */
+  void ready() {}
+
+  void inserted() {
+    if (!_elementPrepared) {
+      prepareElement();
+    }
+    cancelUnbindAll(preventCascade: true);
+  }
+
+  void removed() {
+    asyncUnbindAll();
+  }
+
+  /** Recursive ancestral <element> initialization, oldest first. */
+  void parseDeclarations(PolymerDeclaration declaration) {
+    if (declaration != null) {
+      parseDeclarations(declaration.superDeclaration);
+      parseDeclaration(declaration.host);
+    }
+  }
+
+  /**
+   * Parse input `<polymer-element>` as needed, override for custom behavior.
+   */
+  void parseDeclaration(Element elementElement) {
+    var root = shadowFromTemplate(fetchTemplate(elementElement));
+
+    // Dart note: this is extra code compared to Polymer to support
+    // the getShadowRoot method.
+    if (root == null) return;
+
+    var name = elementElement.attributes['name'];
+    if (name == null) return;
+    _shadowRoots[name] = root;
+  }
+
+  /**
+   * Return a shadow-root template (if desired), override for custom behavior.
+   */
+  Element fetchTemplate(Element elementElement) =>
+      elementElement.query('template');
+
+  /** Utility function that creates a shadow root from a `<template>`. */
+  ShadowRoot shadowFromTemplate(Element template) {
+    if (template == null) return null;
+    // cache elder shadow root (if any)
+    var elderRoot = this.shadowRoot;
+    // make a shadow root
+    var root = createShadowRoot();
+    // migrate flag(s)(
+    root.applyAuthorStyles = applyAuthorStyles;
+    root.resetStyleInheritance = resetStyleInheritance;
+    // stamp template
+    // which includes parsing and applying MDV bindings before being
+    // inserted (to avoid {{}} in attribute values)
+    // e.g. to prevent <img src="images/{{icon}}"> from generating a 404.
+    var dom = instanceTemplate(template);
+    // append to shadow dom
+    root.append(dom);
+    // perform post-construction initialization tasks on shadow root
+    shadowRootReady(root, template);
+    // return the created shadow root
+    return root;
+  }
+
+  void shadowRootReady(ShadowRoot root, Element template) {
+    // locate nodes with id and store references to them in this.$ hash
+    marshalNodeReferences(root);
+    // add local events of interest...
+    addInstanceListeners(root, template);
+    // TODO(jmesserly): port this
+    // set up pointer gestures
+    // PointerGestures.register(root);
+  }
+
+  /** Locate nodes with id and store references to them in [$] hash. */
+  void marshalNodeReferences(ShadowRoot root) {
+    if (root == null) return;
+    for (var n in root.queryAll('[id]')) {
+      $[n.id] = n;
+    }
+  }
+
+  void attributeChanged(String name, String oldValue) {
+    if (name != 'class' && name != 'style') {
+      attributeToProperty(name, attributes[name]);
+    }
+  }
+
+  // TODO(jmesserly): use stream or future here?
+  void onMutation(Node node, void listener(MutationObserver obs)) {
+    new MutationObserver((records, MutationObserver observer) {
+      listener(observer);
+      observer.disconnect();
+    })..observe(node, childList: true, subtree: true);
+  }
+
+  void copyInstanceAttributes() {
+    _declaration._instanceAttributes.forEach((name, value) {
+      attributes[name] = value;
+    });
+  }
+
+  void takeAttributes() {
+    if (_declaration._publishLC == null) return;
+    attributes.forEach(attributeToProperty);
+  }
+
+  /**
+   * If attribute [name] is mapped to a property, deserialize
+   * [value] into that property.
+   */
+  void attributeToProperty(String name, String value) {
+    // try to match this attribute to a property (attributes are
+    // all lower-case, so this is case-insensitive search)
+    var property = propertyForAttribute(name);
+    if (property == null) return;
+
+    // filter out 'mustached' values, these are to be
+    // replaced with bound-data and are not yet values
+    // themselves.
+    if (value == null || value.contains(Polymer.bindPattern)) return;
+
+    // get original value
+    final self = reflect(this);
+    final defaultValue = self.getField(property.simpleName).reflectee;
+
+    // deserialize Boolean or Number values from attribute
+    final newValue = deserializeValue(value, defaultValue,
+        _inferPropertyType(defaultValue, property));
+
+    // only act if the value has changed
+    if (!identical(newValue, defaultValue)) {
+      // install new value (has side-effects)
+      self.setField(property.simpleName, newValue);
+    }
+  }
+
+  /** Return the published property matching name, or null. */
+  // TODO(jmesserly): should we just return Symbol here?
+  DeclarationMirror propertyForAttribute(String name) {
+    final publishLC = _declaration._publishLC;
+    if (publishLC == null) return null;
+    //console.log('propertyForAttribute:', name, 'matches', match);
+    return publishLC[name];
+  }
+
+  /**
+   * Convert representation of [value] based on [type] and [defaultValue].
+   */
+  // TODO(jmesserly): this should probably take a ClassMirror instead of
+  // TypeMirror, but it is currently impossible to get from a TypeMirror to a
+  // ClassMirror.
+  Object deserializeValue(String value, Object defaultValue, TypeMirror type) =>
+      deserialize.deserializeValue(value, defaultValue, type);
+
+  String serializeValue(Object value, TypeMirror inferredType) {
+    if (value == null) return null;
+
+    final type = inferredType.qualifiedName;
+    if (type == const Symbol('dart.core.bool')) {
+      return _toBoolean(value) ? '' : null;
+    } else if (type == const Symbol('dart.core.String')
+        || type == const Symbol('dart.core.int')
+        || type == const Symbol('dart.core.double')) {
+      return '$value';
+    }
+    return null;
+  }
+
+  void reflectPropertyToAttribute(String name) {
+    // TODO(sjmiles): consider memoizing this
+    final self = reflect(this);
+    // try to intelligently serialize property value
+    // TODO(jmesserly): cache symbol?
+    final propValue = self.getField(new Symbol(name)).reflectee;
+    final property = _declaration._publish[name];
+    var inferredType = _inferPropertyType(propValue, property);
+    final serializedValue = serializeValue(propValue, inferredType);
+    // boolean properties must reflect as boolean attributes
+    if (serializedValue != null) {
+      attributes[name] = serializedValue;
+      // TODO(sorvell): we should remove attr for all properties
+      // that have undefined serialization; however, we will need to
+      // refine the attr reflection system to achieve this; pica, for example,
+      // relies on having inferredType object properties not removed as
+      // attrs.
+    } else if (inferredType.qualifiedName == const Symbol('dart.core.bool')) {
+      attributes.remove(name);
+    }
+  }
+
+  /**
+   * Creates the document fragment to use for each instance of the custom
+   * element, given the `<template>` node. By default this is equivalent to:
+   *
+   *     template.createInstance(this, polymerSyntax);
+   *
+   * Where polymerSyntax is a singleton `PolymerExpressions` instance from the
+   * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions)
+   * package.
+   *
+   * You can override this method to change the instantiation behavior of the
+   * template, for example to use a different data-binding syntax.
+   */
+  DocumentFragment instanceTemplate(Element template) =>
+      template.createInstance(this, _polymerSyntax);
+
+  NodeBinding bind(String name, model, String path) {
+    // note: binding is a prepare signal. This allows us to be sure that any
+    // property changes that occur as a result of binding will be observed.
+    if (!_elementPrepared) prepareElement();
+
+    var property = propertyForAttribute(name);
+    if (property != null) {
+      unbind(name);
+      // use n-way Polymer binding
+      var observer = bindProperty(property.simpleName, model, path);
+      // reflect bound property to attribute when binding
+      // to ensure binding is not left on attribute if property
+      // does not update due to not changing.
+      reflectPropertyToAttribute(name);
+      return bindings[name] = observer;
+    } else {
+      return super.bind(name, model, path);
+    }
+  }
+
+  void asyncUnbindAll() {
+    if (_unbound == true) return;
+    _unbindLog.info('[$localName] asyncUnbindAll');
+    _unbindAllJob = job(_unbindAllJob, unbindAll, const Duration(seconds: 0));
+  }
+
+  void unbindAll() {
+    if (_unbound == true) return;
+
+    unbindAllProperties();
+    super.unbindAll();
+    _unbindNodeTree(shadowRoot);
+    // TODO(sjmiles): must also unbind inherited shadow roots
+    _unbound = true;
+  }
+
+  void cancelUnbindAll({bool preventCascade}) {
+    if (_unbound == true) {
+      _unbindLog.warning(
+          '[$localName] already unbound, cannot cancel unbindAll');
+      return;
+    }
+    _unbindLog.info('[$localName] cancelUnbindAll');
+    if (_unbindAllJob != null) {
+      _unbindAllJob.stop();
+      _unbindAllJob = null;
+    }
+
+    // cancel unbinding our shadow tree iff we're not in the process of
+    // cascading our tree (as we do, for example, when the element is inserted).
+    if (preventCascade == true) return;
+    _forNodeTree(shadowRoot, (n) {
+      if (n is PolymerElement) {
+        (n as PolymerElement).cancelUnbindAll();
+      }
+    });
+  }
+
+  static void _unbindNodeTree(Node node) {
+    _forNodeTree(node, (node) => node.unbindAll());
+  }
+
+  static void _forNodeTree(Node node, void callback(Node node)) {
+    if (node == null) return;
+
+    callback(node);
+    for (var child = node.firstChild; child != null; child = child.nextNode) {
+      _forNodeTree(child, callback);
+    }
+  }
+
+  /** Set up property observers. */
+  void observeProperties() {
+    // TODO(sjmiles):
+    // we observe published properties so we can reflect them to attributes
+    // ~100% of our team's applications would work without this reflection,
+    // perhaps we can make it optional somehow
+    //
+    // add user's observers
+    final observe = _declaration._observe;
+    final publish = _declaration._publish;
+    if (observe != null) {
+      observe.forEach((name, value) {
+        if (publish != null && publish.containsKey(name)) {
+          observeBoth(name, value);
+        } else {
+          observeProperty(name, value);
+        }
+      });
+    }
+    // add observers for published properties
+    if (publish != null) {
+      publish.forEach((name, value) {
+        if (observe == null || !observe.containsKey(name)) {
+          observeAttributeProperty(name);
+        }
+      });
+    }
+  }
+
+  void _observe(String name, void callback(newValue, oldValue)) {
+    _observeLog.info('[$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.
+    var path = new PathObserver(this, name);
+    Object oldValue = null;
+    _registerObserver(name, path.changes.listen((_) {
+      final newValue = path.value;
+      final old = oldValue;
+      oldValue = newValue;
+      callback(newValue, old);
+    }));
+  }
+
+  void _registerObserver(String name, StreamSubscription sub) {
+    if (_elementObservers == null) {
+      _elementObservers = new Map<String, StreamSubscription>();
+    }
+    _elementObservers[name] = sub;
+  }
+
+  void observeAttributeProperty(String name) {
+    _observe(name, (value, old) => reflectPropertyToAttribute(name));
+  }
+
+  void observeProperty(String name, Symbol method) {
+    final self = reflect(this);
+    _observe(name, (value, old) => self.invoke(method, [old]));
+  }
+
+  void observeBoth(String name, Symbol methodName) {
+    final self = reflect(this);
+    _observe(name, (value, old) {
+      reflectPropertyToAttribute(name);
+      self.invoke(methodName, [old]);
+    });
+  }
+
+  void unbindProperty(String name) {
+    if (_elementObservers == null) return;
+    var sub = _elementObservers.remove(name);
+    if (sub != null) sub.cancel();
+  }
+
+  void unbindAllProperties() {
+    if (_elementObservers == null) return;
+    for (var sub in _elementObservers.values) sub.cancel();
+    _elementObservers.clear();
+  }
+
+  /**
+   * Bind a [property] in this object to a [path] in model. *Note* in Dart it
+   * is necessary to also define the field:
+   *
+   *     var myProperty;
+   *
+   *     created() {
+   *       super.created();
+   *       bindProperty(#myProperty, this, 'myModel.path.to.otherProp');
+   *     }
+   */
+  // TODO(jmesserly): replace with something more localized, like:
+  // @ComputedField('myModel.path.to.otherProp');
+  NodeBinding bindProperty(Symbol name, Object model, String path) =>
+      // apply Polymer two-way reference binding
+      _bindProperties(this, name, model, path);
+
+  /**
+   * bind a property in A to a path in B by converting A[property] to a
+   * getter/setter pair that accesses B[...path...]
+   */
+  static NodeBinding _bindProperties(PolymerElement inA, Symbol inProperty,
+        Object inB, String inPath) {
+
+    if (_bindLog.isLoggable(Level.INFO)) {
+      _bindLog.info('[$inB]: bindProperties: [$inPath] to '
+          '[${inA.localName}].[$inProperty]');
+    }
+
+    // Dart note: normally we only reach this code when we know it's a
+    // property, but if someone uses bindProperty directly they might get a
+    // NoSuchMethodError either from the getField below, or from the setField
+    // inside PolymerBinding. That doesn't seem unreasonable, but it's a slight
+    // difference from Polymer.js behavior.
+
+    // capture A's value if B's value is null or undefined,
+    // otherwise use B's value
+    var path = new PathObserver(inB, inPath);
+    if (path.value == null) {
+      path.value = reflect(inA).getField(inProperty).reflectee;
+    }
+    return new _PolymerBinding(inA, inProperty, inB, inPath);
+  }
+
+  /** Attach event listeners on the host (this) element. */
+  void addHostListeners() {
+    var events = _declaration._eventDelegates;
+    if (events.isEmpty) return;
+
+    if (_eventsLog.isLoggable(Level.INFO)) {
+      _eventsLog.info('[$localName] addHostListeners: $events');
+    }
+    addNodeListeners(this, events.keys, hostEventListener);
+  }
+
+  /** Attach event listeners inside a shadow [root]. */
+  void addInstanceListeners(ShadowRoot root, Element template) {
+    var templateDelegates = _declaration._templateDelegates;
+    if (templateDelegates == null) return;
+    var events = templateDelegates[template];
+    if (events == null) return;
+
+    if (_eventsLog.isLoggable(Level.INFO)) {
+      _eventsLog.info('[$localName] addInstanceListeners: $events');
+    }
+    addNodeListeners(root, events, instanceEventListener);
+  }
+
+  void addNodeListeners(Node node, Iterable<String> events,
+      void listener(Event e)) {
+
+    for (var name in events) {
+      addNodeListener(node, name, listener);
+    }
+  }
+
+  void addNodeListener(Node node, String event, void listener(Event e)) {
+    node.on[event].listen(listener);
+  }
+
+  void hostEventListener(Event event) {
+    // TODO(jmesserly): do we need this check? It was using cancelBubble, see:
+    // https://github.com/Polymer/polymer/issues/292
+    if (!event.bubbles) return;
+
+    bool log = _eventsLog.isLoggable(Level.INFO);
+    if (log) {
+      _eventsLog.info('>>> [$localName]: hostEventListener(${event.type})');
+    }
+
+    var h = findEventDelegate(event);
+    if (h != null) {
+      if (log) _eventsLog.info('[$localName] found host handler name [$h]');
+      var detail = event is CustomEvent ?
+          (event as CustomEvent).detail : null;
+      // TODO(jmesserly): cache the symbols?
+      dispatchMethod(new Symbol(h), [event, detail, this]);
+    }
+
+    if (log) {
+      _eventsLog.info('<<< [$localName]: hostEventListener(${event.type})');
+    }
+  }
+
+  String findEventDelegate(Event event) =>
+      _declaration._eventDelegates[_eventNameFromType(event.type)];
+
+  /** 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');
+
+    // TODO(sigmund): consider making event listeners list all arguments
+    // explicitly. Unless VM mirrors are optimized first, this reflectClass call
+    // will be expensive once custom elements extend directly from Element (see
+    // dartbug.com/11108).
+    var self = reflect(this);
+    var method = self.type.methods[methodName];
+    if (method != null) {
+      // This will either truncate the argument list or extend it with extra
+      // null arguments, so it will match the signature.
+      // TODO(sigmund): consider accepting optional arguments when we can tell
+      // them appart from named arguments (see http://dartbug.com/11334)
+      args.length = method.parameters.where((p) => !p.isOptional).length;
+    }
+    self.invoke(methodName, args);
+
+    if (log) _eventsLog.info('<<< [$localName]: dispatch $methodName');
+
+    // TODO(jmesserly): workaround for HTML events not supporting zones.
+    performMicrotaskCheckpoint();
+  }
+
+  void instanceEventListener(Event event) {
+    _listenLocal(host, event);
+  }
+
+  // TODO(sjmiles): much of the below privatized only because of the vague
+  // notion this code is too fiddly and we need to revisit the core feature
+  void _listenLocal(Element host, Event event) {
+    // TODO(jmesserly): do we need this check? It was using cancelBubble, see:
+    // 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}]');
+
+    final eventOn = '$_EVENT_PREFIX${_eventNameFromType(event.type)}';
+    if (event.path == null) {
+      _listenLocalNoEventPath(host, event, eventOn);
+    } else {
+      _listenLocalEventPath(host, event, eventOn);
+    }
+
+    if (log) _eventsLog.info('<<< [$localName]: listenLocal [${event.type}]');
+  }
+
+  static void _listenLocalEventPath(Element host, Event event, String eventOn) {
+    var c = null;
+    for (var target in event.path) {
+      // if we hit host, stop
+      if (identical(target, host)) return;
+
+      // find a controller for the target, unless we already found `host`
+      // as a controller
+      c = identical(c, host) ? c : _findController(target);
+
+      // if we have a controller, dispatch the event, and stop if the handler
+      // returns true
+      if (c != null && _handleEvent(c, target, event, eventOn)) {
+        return;
+      }
+    }
+  }
+
+  // TODO(sorvell): remove when ShadowDOM polyfill supports event path.
+  // Note that _findController will not return the expected controller when the
+  // event target is a distributed node.  This is because we cannot traverse
+  // from a composed node to a node in shadowRoot.
+  // This will be addressed via an event path api
+  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066
+  static void _listenLocalNoEventPath(Element host, Event event,
+      String eventOn) {
+
+    if (_eventsLog.isLoggable(Level.INFO)) {
+      _eventsLog.info('event.path() not supported for ${event.type}');
+    }
+
+    var target = event.target;
+    var c = null;
+    // if we hit dirt or host, stop
+    while (target != null && target != host) {
+      // find a controller for target `t`, unless we already found `host`
+      // as a controller
+      c = identical(c, host) ? c : _findController(target);
+
+      // if we have a controller, dispatch the event, return 'true' if
+      // handler returns true
+      if (c != null && _handleEvent(c, target, event, eventOn)) {
+        return;
+      }
+      target = target.parent;
+    }
+  }
+
+  // TODO(jmesserly): this won't find the correct host unless the ShadowRoot
+  // was created on a PolymerElement.
+  static Element _findController(Node node) {
+    while (node.parentNode != null) {
+      node = node.parentNode;
+    }
+    return _shadowHost[node];
+  }
+
+  static bool _handleEvent(Element ctrlr, Node node, Event event,
+      String eventOn) {
+
+    // Note: local events are listened only in the shadow root. This dynamic
+    // lookup is used to distinguish determine whether the target actually has a
+    // 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]');
+      }
+      var detail = event is CustomEvent ?
+          (event as CustomEvent).detail : null;
+
+      if (node != null) {
+        // TODO(jmesserly): cache symbols?
+        ctrlr.xtag.dispatchMethod(new Symbol(name), [event, detail, node]);
+      }
+    }
+
+    // TODO(jmesserly): do we need this? It was using cancelBubble, see:
+    // https://github.com/Polymer/polymer/issues/292
+    return !event.bubbles;
+  }
+
+  // TODO(jmesserly): I don't understand this bit. It seems to be a duplicate
+  // delivery prevention mechanism?
+  static bool _handleIfNotHandled(Node node, Event event) {
+    var list = _eventHandledTable[event];
+    if (list == null) _eventHandledTable[event] = list = new Set<Node>();
+    if (!list.contains(node)) {
+      list.add(node);
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Invokes a function asynchronously.
+   * This will call `Platform.flush()` and then return a `new Timer`
+   * with the provided [method] and [timeout].
+   *
+   * If you would prefer to run the callback using
+   * [window.requestAnimationFrame], see the [async] method.
+   */
+  // Dart note: "async" is split into 2 methods so it can have a sensible type
+  // signatures. Also removed the various features that don't make sense in a
+  // Dart world, like binding to "this" and taking arguments list.
+  Timer asyncTimer(void method(), Duration timeout) {
+    // when polyfilling Object.observe, ensure changes
+    // propagate before executing the async method
+    platform.flush();
+    return new Timer(timeout, method);
+  }
+
+  /**
+   * Invokes a function asynchronously.
+   * This will call `Platform.flush()` and then call
+   * [window.requestAnimationFrame] with the provided [method] and return the
+   * result.
+   *
+   * If you would prefer to run the callback after a given duration, see
+   * the [asyncTimer] method.
+   */
+  int async(RequestAnimationFrameCallback method) {
+    // when polyfilling Object.observe, ensure changes
+    // propagate before executing the async method
+    platform.flush();
+    return window.requestAnimationFrame(method);
+  }
+
+  /**
+   * Fire a [CustomEvent] targeting [toNode], or this if toNode is not
+   * supplied. Returns the [detail] object.
+   */
+  Object fire(String type, {Object detail, Node toNode, bool canBubble}) {
+    var node = toNode != null ? toNode : this;
+    //log.events && console.log('[%s]: sending [%s]', node.localName, inType);
+    node.dispatchEvent(new CustomEvent(
+      type,
+      canBubble: canBubble != null ? canBubble : true,
+      detail: detail
+    ));
+    return detail;
+  }
+
+  /**
+   * Fire an event asynchronously. See [async] and [fire].
+   */
+  asyncFire(String type, {Object detail, Node toNode, bool canBubble}) {
+    // TODO(jmesserly): I'm not sure this method adds much in Dart, it's easy to
+    // add "() =>"
+    async((x) => fire(
+        type, detail: detail, toNode: toNode, canBubble: canBubble));
+  }
+
+  /**
+   * Remove [className] from [old], add class to [anew], if they exist.
+   */
+  void classFollows(Element anew, Element old, String className) {
+    if (old != null) {
+      old.classes.remove(className);
+    }
+    if (anew != null) {
+      anew.classes.add(className);
+    }
+  }
+}
+
+// Dart note: Polymer addresses n-way bindings by metaprogramming: redefine
+// the property on the PolymerElement instance to always get its value from the
+// model@path. We can't replicate this in Dart so we do the next best thing:
+// listen to changes on both sides and update the values.
+// TODO(jmesserly): our approach leads to race conditions in the bindings.
+// See http://code.google.com/p/dart/issues/detail?id=13567
+class _PolymerBinding extends NodeBinding {
+  final InstanceMirror _target;
+  final Symbol _property;
+  StreamSubscription _sub;
+  Object _lastValue;
+
+  _PolymerBinding(PolymerElement node, Symbol property, model, path)
+      : _target = reflect(node),
+        _property = property,
+        super(node, MirrorSystem.getName(property), model, path) {
+
+    _sub = node.changes.listen(_propertyValueChanged);
+  }
+
+  void close() {
+    if (closed) return;
+    _sub.cancel();
+    super.close();
+  }
+
+  void boundValueChanged(newValue) {
+    _lastValue = newValue;
+    _target.setField(_property, newValue);
+  }
+
+  void _propertyValueChanged(List<ChangeRecord> records) {
+    for (var record in records) {
+      if (record.changes(_property)) {
+        final newValue = _target.getField(_property).reflectee;
+        if (!identical(_lastValue, newValue)) {
+          value = newValue;
+        }
+        return;
+      }
+    }
+  }
+}
+
+bool _toBoolean(value) => null != value && false != value;
+
+TypeMirror _propertyType(DeclarationMirror property) =>
+    property is VariableMirror
+        ? (property as VariableMirror).type
+        : (property as MethodMirror).returnType;
+
+TypeMirror _inferPropertyType(Object value, DeclarationMirror property) {
+  var type = _propertyType(property);
+  if (type.qualifiedName == const Symbol('dart.core.Object') ||
+      type.qualifiedName == const Symbol('dynamic')) {
+    // Attempt to infer field type from the default value.
+    if (value != null) {
+      type = reflect(value).type;
+    }
+  }
+  return type;
+}
+
+final Logger _observeLog = new Logger('polymer.observe');
+final Logger _eventsLog = new Logger('polymer.events');
+final Logger _unbindLog = new Logger('polymer.unbind');
+final Logger _bindLog = new Logger('polymer.bind');
+
+final Expando _shadowHost = new Expando<Element>();
+
+final Expando _eventHandledTable = new Expando<Set<Node>>();
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart
new file mode 100644
index 0000000..e8cbb90
--- /dev/null
+++ b/pkg/polymer/lib/src/loader.dart
@@ -0,0 +1,130 @@
+// 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 polymer;
+
+/** Annotation used to automatically register polymer elements. */
+class CustomTag {
+  final String tagName;
+  const CustomTag(this.tagName);
+}
+
+/**
+ * Metadata used to label static or top-level methods that are called
+ * automatically when loading the library of a custom element.
+ */
+const initMethod = const _InitMethodAnnotation();
+
+/**
+ * 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.
+ *
+ * The initialization on each library is either a method named `main` or
+ * a top-level function and annotated with [initMethod].
+ *
+ * The urls in [libraries] can be absolute or relative to [srcUrl].
+ */
+void initPolymer(List<String> libraries, [String srcUrl]) {
+  runMicrotask(() {
+    // DOM events don't yet go through microtasks, so we catch those here.
+    new Timer.periodic(new Duration(milliseconds: 125),
+        (_) => performMicrotaskCheckpoint());
+
+    // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize.
+    mdv.initialize();
+    registerCustomElement('polymer-element', () => new PolymerDeclaration());
+
+    for (var lib in libraries) {
+      _loadLibrary(lib, srcUrl);
+    }
+
+    // TODO(jmesserly): this should be in the custom_element polyfill, not here.
+    // notify the system that we are bootstrapped
+    document.body.dispatchEvent(
+        new CustomEvent('WebComponentsReady', canBubble: true));
+  });
+}
+
+/** All libraries in the current isolate. */
+final _libs = currentMirrorSystem().libraries;
+
+/**
+ * Reads the library at [uriString] (which can be an absolute URI or a relative
+ * URI from [srcUrl]), and:
+ *
+ *   * If present, invokes `main`.
+ *
+ *   * If present, invokes any top-level and static functions marked
+ *     with the [initMethod] annotation (in the order they appear).
+ *
+ *   * 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)));
+  }
+  var lib = _libs[uri];
+  if (lib == null) {
+    print('warning: $uri library not found');
+    return;
+  }
+
+  // Invoke `main`, if present.
+  if (lib.functions[const Symbol('main')] != null) {
+    lib.invoke(const Symbol('main'), const []);
+  }
+
+  // Search top-level functions marked with @initMethod
+  for (var f in lib.functions.values) {
+    _maybeInvoke(lib, f);
+  }
+
+  for (var c in lib.classes.values) {
+    // Search for @CustomTag on classes
+    for (var m in c.metadata) {
+      var meta = m.reflectee;
+      if (meta is CustomTag) {
+        Polymer._registerClassMirror(meta.tagName, c);
+      }
+    }
+
+    // TODO(sigmund): check also static methods marked with @initMethod.
+    // This is blocked on two bugs:
+    //  - dartbug.com/12133 (static methods are incorrectly listed as top-level
+    //    in dart2js, so they end up being called twice)
+    //  - dartbug.com/12134 (sometimes "method.metadata" throws an exception,
+    //    we could wrap and hide those exceptions, but it's not ideal).
+  }
+}
+
+void _maybeInvoke(ObjectMirror obj, MethodMirror method) {
+  var annotationFound = false;
+  for (var meta in method.metadata) {
+    if (identical(meta.reflectee, initMethod)) {
+      annotationFound = true;
+      break;
+    }
+  }
+  if (!annotationFound) return;
+  if (!method.isStatic) {
+    print("warning: methods marked with @initMethod should be static,"
+        " ${method.simpleName} is not.");
+    return;
+  }
+  if (!method.parameters.where((p) => !p.isOptional).isEmpty) {
+    print("warning: methods marked with @initMethod should take no "
+        "arguments, ${method.simpleName} expects some.");
+    return;
+  }
+  obj.invoke(method.simpleName, const []);
+}
+
+class _InitMethodAnnotation {
+  const _InitMethodAnnotation();
+}
diff --git a/pkg/polymer/lib/transformer.dart b/pkg/polymer/lib/transformer.dart
index 5f4dc02..26d5678 100644
--- a/pkg/polymer/lib/transformer.dart
+++ b/pkg/polymer/lib/transformer.dart
@@ -6,6 +6,7 @@
 // TODO(sigmund): move into a plugin directory when pub supports it.
 library polymer.src.transform;
 
+import 'package:barback/barback.dart';
 import 'package:observe/transform.dart';
 import 'src/build/code_extractor.dart';
 import 'src/build/import_inliner.dart';
diff --git a/pkg/polymer/pubspec.yaml b/pkg/polymer/pubspec.yaml
index 4d93ad5..acd745f 100644
--- a/pkg/polymer/pubspec.yaml
+++ b/pkg/polymer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: polymer
-author: Web UI Authors <web-ui-dev@dartlang.org>
+author: Polymer.dart Authors <web-ui-dev@dartlang.org>
 description: >
   Polymer.dart is a new type of library for the web, built on top of Web
   Components, and designed to leverage the evolving web platform on modern
@@ -16,11 +16,12 @@
   html_import: any
   logging: any
   mdv: any
+  meta: any
   observe: any
   path: any
   polymer_expressions: any
   shadow_dom: any
   source_maps: any
-  # TODO(jmesserly): make this a dev_dependency
-  unittest: any
   yaml: any
+dev_dependencies:
+  unittest: any
diff --git a/pkg/polymer/test/attr_deserialize_test.dart b/pkg/polymer/test/attr_deserialize_test.dart
new file mode 100644
index 0000000..8497752
--- /dev/null
+++ b/pkg/polymer/test/attr_deserialize_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('my-element')
+class MyElement extends PolymerElement {
+  @published double volume;
+  @published int factor;
+  @published bool crankIt;
+  @published String msg;
+  @published DateTime time;
+  @published Object json;
+}
+
+main() {
+  useHtmlConfiguration();
+
+  test('attributes were deserialized', () {
+    MyElement elem = query('my-element').xtag;
+    final msg = 'property should match attribute.';
+    expect(elem.volume, 11.0, reason: '"volume" should match attribute');
+    expect(elem.factor, 3, reason: '"factor" should match attribute');
+    expect(elem.crankIt, true, reason: '"crankIt" should match attribute');
+    expect(elem.msg, "Yo!", reason: '"msg" should match attribute');
+    expect(elem.time, DateTime.parse('2013-08-08T18:34Z'),
+        reason: '"time" should match attribute');
+    expect(elem.json, {'here': 'is', 'some': 'json', 'x': 123},
+        reason: '"json" should match attribute');
+
+    var text = elem.shadowRoot.text;
+    // Collapse adjacent whitespace like a browser would:
+    text = text.replaceAll('\n', ' ').replaceAll(new RegExp(r'\s+'), ' ');
+
+    // Note: using "${33.0}" because the toString differs in JS vs Dart VM.
+    expect(text, " Yo! The volume is ${33.0} !! The time is "
+        "2013-08-08 18:34:00.000Z and here's some JSON: "
+        "{here: is, some: json, x: 123} ",
+        reason: 'text should match expected HTML template');
+  });
+}
diff --git a/pkg/polymer/test/attr_deserialize_test.html b/pkg/polymer/test/attr_deserialize_test.html
new file mode 100644
index 0000000..de10fac
--- /dev/null
+++ b/pkg/polymer/test/attr_deserialize_test.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <head>
+    <title>Polymer.dart attribute deserialization test</title>
+    <script src="packages/polymer/boot.js"></script>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+    <polymer-element name="my-element">
+      <template>
+        <h1>{{msg}} The volume is {{volume * factor}}
+          <template if="{{crankIt}}">!!</template></h1>
+        <h3>The time is {{time}} and here's some JSON: {{json}}</h3>
+      </template>
+    </polymer-element>
+
+    <my-element volume="11" crankit msg="Yo!" factor="3"
+        time="2013-08-08T18:34Z"
+        json="{'here': 'is', 'some': 'json', 'x': 123}">
+    </my-element>
+
+    <script type="application/dart" src="attr_deserialize_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/test/attr_mustache_test.dart b/pkg/polymer/test/attr_mustache_test.dart
new file mode 100644
index 0000000..fba0171
--- /dev/null
+++ b/pkg/polymer/test/attr_mustache_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('x-target')
+class XTarget extends PolymerElement {
+  final Completer _found = new Completer();
+  Future get foundSrc => _found.future;
+
+  // force an mdv binding
+  bind(name, model, path) =>
+      TemplateElement.mdvPackage(this).bind(name, model, path);
+
+  inserted() {
+    testSrcForMustache();
+  }
+
+  attributeChanged(name, oldValue) {
+    testSrcForMustache();
+    if (attributes[name] == '../testSource') {
+      _found.complete();
+    }
+  }
+
+  testSrcForMustache() {
+    expect(attributes['src'], isNot(matches(Polymer.bindPattern)),
+        reason: 'attribute does not contain {{...}}');
+  }
+}
+
+@CustomTag('x-test')
+class XTest extends PolymerElement {
+  @observable var src = 'testSource';
+}
+
+main() {
+  useHtmlConfiguration();
+
+  test('mustache attributes', () {
+    final xtest = document.query('#test').xtag;
+    final xtarget = xtest.shadowRoot.query('#target').xtag;
+    return xtarget.foundSrc;
+  });
+}
diff --git a/pkg/polymer/test/attr_mustache_test.html b/pkg/polymer/test/attr_mustache_test.html
new file mode 100644
index 0000000..df9f9ee
--- /dev/null
+++ b/pkg/polymer/test/attr_mustache_test.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <head>
+    <title>take attributes</title>
+    <script src="packages/polymer/boot.js"></script>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+    <x-test id="test"></x-test>
+
+    <polymer-element name="x-target" attributes="src">
+    </polymer-element>
+
+    <polymer-element name="x-test">
+      <template>
+        <x-target id="target" src="../{{src}}"></x-target>
+      </template>
+    </polymer-element>
+
+  <script type="application/dart" src="attr_mustache_test.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 1c2dccc..9e6a9b7 100644
--- a/pkg/polymer/test/build/all_phases_test.dart
+++ b/pkg/polymer/test/build/all_phases_test.dart
@@ -198,17 +198,14 @@
 }
 ''';
 
-String _sampleObservableOutput(String className, String fieldName) => '''
-library ${className}_$fieldName;
-import 'package:observe/observe.dart';
-
-class $className extends ChangeNotifierBase {
-  int __\$$fieldName;
-  int get $fieldName => __\$$fieldName;
-  set $fieldName(int value) {
-    __\$$fieldName = notifyPropertyChange(const Symbol('$fieldName'), __\$$fieldName, value);
-  }
-
-  $className($fieldName) : __\$$fieldName = $fieldName;
-}
-''';
+String _sampleObservableOutput(String className, String field) =>
+    "library ${className}_$field;\n"
+    "import 'package:observe/observe.dart';\n\n"
+    "class $className extends ChangeNotifierBase {\n"
+    "  @observable int get $field => __\$$field; "
+      "int __\$$field; "
+      "set $field(int value) { "
+      "__\$$field = notifyPropertyChange(#$field, __\$$field, value); "
+      "}\n"
+    "  $className($field) : __\$$field = $field;\n"
+    "}\n";
diff --git a/pkg/polymer/test/build/linter_test.dart b/pkg/polymer/test/build/linter_test.dart
index e4f3630..17975a8 100644
--- a/pkg/polymer/test/build/linter_test.dart
+++ b/pkg/polymer/test/build/linter_test.dart
@@ -261,7 +261,7 @@
             'JavaScript event handler. Use the form '
             'on-event-name="handlerName" if you want a Dart handler '
             'that will automatically update the UI based on model changes. '
-            '(lib/test.html 1 0)'
+            '(lib/test.html 1 5)'
       });
 
     _testLinter('on-foo is only supported in polymer elements', {
@@ -272,7 +272,7 @@
         'a|lib/test.html.messages':
             'warning: Inline event handlers are only supported inside '
             'declarations of <polymer-element>. '
-            '(lib/test.html 1 0)'
+            '(lib/test.html 1 5)'
       });
 
     _testLinter('on-foo is not an expression', {
@@ -285,7 +285,20 @@
             'warning: Invalid event handler body "bar()". Declare a method '
             'in your custom element "void handlerName(event, detail, target)" '
             'and use the form on-foo="handlerName". '
-            '(lib/test.html 1 28)'
+            '(lib/test.html 1 33)'
+      });
+
+    _testLinter('on-foo-bar is no longer supported', {
+        'a|lib/test.html': '''<html><body>
+            <polymer-element name="x-a"><div on-foo-bar="quux"></div>
+            </polymer-element>
+            '''.replaceAll('            ', ''),
+      }, {
+        'a|lib/test.html.messages':
+            'warning: Invalid event name "on-foo-bar". After the "on-" the '
+            'event name should not use dashes. For example use "on-fooBar" or '
+            '"on-foobar" (both forms are equivalent in HTML). '
+            '(lib/test.html 1 33)'
       });
   });
 
@@ -294,7 +307,7 @@
         'a|lib/test.html': '<x-foo></x-foo>',
       }, {
         'a|lib/test.html.messages':
-            'warning: definition for custom element with tag name "x-foo" not '
+            'warning: definition for Polymer element with tag name "x-foo" not '
             'found. (lib/test.html 0 0)'
       });
 
@@ -302,7 +315,7 @@
         'a|lib/test.html': '<div is="x-foo"></div>',
       }, {
         'a|lib/test.html.messages':
-            'warning: definition for custom element with tag name "x-foo" not '
+            'warning: definition for Polymer element with tag name "x-foo" not '
             'found. (lib/test.html 0 0)'
       });
 
@@ -409,6 +422,20 @@
             'to write <li is="x-a">? (lib/test.html 1 0)'
       });
   });
+
+  group('custom attributes', () {
+    _testLinter('foo-bar is no longer supported in attributes', {
+        'a|lib/test.html': '''<html><body>
+            <polymer-element name="x-a" attributes="foo-bar">
+            </polymer-element>
+            '''.replaceAll('            ', ''),
+      }, {
+        'a|lib/test.html.messages':
+            'warning: PolymerElement no longer recognizes attribute names with '
+            'dashes such as "foo-bar". Use "fooBar" or "foobar" instead (both '
+            'forms are equivalent in HTML). (lib/test.html 1 28)'
+      });
+  });
 }
 
 _testLinter(String name, Map inputFiles, Map outputMessages) {
diff --git a/pkg/polymer/test/utils_test.dart b/pkg/polymer/test/build/utils_test.dart
similarity index 98%
rename from pkg/polymer/test/utils_test.dart
rename to pkg/polymer/test/build/utils_test.dart
index 335e538..cd99656 100644
--- a/pkg/polymer/test/utils_test.dart
+++ b/pkg/polymer/test/build/utils_test.dart
@@ -7,7 +7,7 @@
 
 import 'package:unittest/compact_vm_config.dart';
 import 'package:unittest/unittest.dart';
-import 'package:polymer/src/utils.dart';
+import 'package:polymer/src/build/utils.dart';
 
 main() {
   useCompactVMConfiguration();
diff --git a/pkg/polymer/test/prop_attr_reflection_test.dart b/pkg/polymer/test/prop_attr_reflection_test.dart
new file mode 100644
index 0000000..d74f5e4
--- /dev/null
+++ b/pkg/polymer/test/prop_attr_reflection_test.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/platform.dart' as Platform;
+import 'package:polymer/polymer.dart';
+
+class XFoo extends PolymerElement {
+  @observable var foo = '';
+  @observable String baz = '';
+}
+
+class XBar extends XFoo {
+  @observable int zot = 3;
+  @observable bool zim = false;
+  @observable String str = 'str';
+  @observable Object obj;
+}
+
+class XCompose extends PolymerElement {
+  @observable bool zim = false;
+}
+
+main() {
+  useHtmlConfiguration();
+
+  // Most tests use @CustomTag, here we test out the impertive register:
+  Polymer.register('x-foo', XFoo);
+  Polymer.register('x-bar', XBar);
+  Polymer.register('x-compose', XCompose);
+
+  test('property attribute reflection', () {
+    var xcompose = query('x-compose').xtag;
+    var xfoo = query('x-foo').xtag;
+    xfoo.foo = 5;
+    Platform.flush();
+    Platform.endOfMicrotask(expectAsync0(() {
+      expect(xcompose.$['bar'].attributes.containsKey('zim'), false,
+          reason: 'attribute bound to property updates when binding is made');
+
+      expect('${xfoo.foo}', xfoo.attributes['foo'],
+          reason: 'attribute reflects property as string');
+      xfoo.attributes['foo'] = '27';
+      // TODO(jmesserly): why is JS leaving this as a String? From the code it
+      // looks like it should use the type of 5 and parse it as a number.
+      expect('${xfoo.foo}', xfoo.attributes['foo'],
+          reason: 'property reflects attribute');
+      //
+      xfoo.baz = 'Hello';
+      Platform.flush();
+      Platform.endOfMicrotask(expectAsync0(() {
+        expect(xfoo.baz, xfoo.attributes['baz'],
+            reason: 'attribute reflects property');
+        //
+        var xbar = query('x-bar').xtag;
+        //
+        xbar.foo = 'foo!';
+        xbar.zot = 27;
+        xbar.zim = true;
+        xbar.str = 'str!';
+        xbar.obj = {'hello': 'world'};
+        Platform.flush();
+        Platform.endOfMicrotask(expectAsync0(() {
+          expect(xbar.foo, xbar.attributes['foo'],
+              reason: 'inherited published property is reflected');
+          expect('${xbar.zot}', xbar.attributes['zot'],
+              reason: 'attribute reflects property as number');
+          expect(xbar.attributes['zim'], '', reason:
+              'attribute reflects true valued boolean property as '
+              'having attribute');
+          expect(xbar.str, xbar.attributes['str'],
+              reason: 'attribute reflects property as published string');
+          expect(xbar.attributes.containsKey('obj'), false,
+              reason: 'attribute does not reflect object property');
+          xbar.attributes['zim'] = 'false';
+          xbar.attributes['foo'] = 'foo!!';
+          xbar.attributes['zot'] = '54';
+          xbar.attributes['str'] = 'str!!';
+          xbar.attributes['obj'] = "{'hello': 'world'}";
+          expect(xbar.foo, xbar.attributes['foo'],
+              reason: 'property reflects attribute as string');
+          expect(xbar.zot, 54,
+              reason: 'property reflects attribute as number');
+          expect(xbar.zim, false,
+              reason: 'property reflects attribute as boolean');
+          expect(xbar.str, 'str!!',
+              reason: 'property reflects attribute as published string');
+          expect(xbar.obj, {'hello': 'world'},
+              reason: 'property reflects attribute as object');
+          xbar.zim = false;
+          Platform.flush();
+          Platform.endOfMicrotask(expectAsync0(() {
+            expect(xbar.attributes.containsKey('zim'), false, reason:
+                'attribute reflects false valued boolean property as NOT '
+                'having attribute');
+            var objAttr = xbar.attributes['obj'];
+            xbar.obj = 'hi';
+            Platform.endOfMicrotask(expectAsync0(() {
+              expect(xbar.attributes['obj'], objAttr, reason:
+                  'do not reflect property with default type of object');
+            }));
+          }));
+        }));
+      }));
+    }));
+  });
+}
diff --git a/pkg/polymer/test/prop_attr_reflection_test.html b/pkg/polymer/test/prop_attr_reflection_test.html
new file mode 100644
index 0000000..e4466d3
--- /dev/null
+++ b/pkg/polymer/test/prop_attr_reflection_test.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <head>
+    <title>publish attributes</title>
+    <script src="packages/polymer/boot.js"></script>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+    <x-foo></x-foo>
+    <polymer-element name="x-foo" attributes="foo baz">
+    </polymer-element>
+
+    <x-bar></x-bar>
+    <polymer-element name="x-bar" extends="x-foo" attributes="zot zim str obj">
+    </polymer-element>
+
+    <x-compose></x-compose>
+    <polymer-element name="x-compose">
+      <template>
+        <x-bar id="bar" zim="{{zim}}"></x-bar>
+      </template>
+    </polymer-element>
+
+  <script type="application/dart" src="prop_attr_reflection_test.dart"></script>
+  </body>
+</html>
\ No newline at end of file
diff --git a/pkg/polymer/test/publish_attributes_test.dart b/pkg/polymer/test/publish_attributes_test.dart
new file mode 100644
index 0000000..e31b74f
--- /dev/null
+++ b/pkg/polymer/test/publish_attributes_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+// Dart note: unlike JS, you can't publish something that doesn't
+// have a corresponding field because we can't dynamically add properties.
+// So we define XFoo and XBar types here.
+@CustomTag('x-foo')
+class XFoo extends PolymerElement {
+  @observable var Foo;
+  @observable var baz;
+}
+
+@CustomTag('x-bar')
+class XBar extends XFoo {
+  @observable var Bar;
+}
+
+@CustomTag('x-zot')
+class XZot extends XBar {
+  @published int zot = 3;
+}
+
+@CustomTag('x-squid')
+class XSquid extends XZot {
+  @published int baz = 13;
+  @published int zot = 5;
+  @published int squid = 7;
+}
+
+main() {
+  useHtmlConfiguration();
+
+  test('published properties', () {
+    published(tag) =>
+        query('polymer-element[name=$tag]').xtag.publishedProperties;
+
+    print(published('x-foo'));
+    print(published('x-bar'));
+    print(published('x-zot'));
+    print(published('x-squid'));
+
+    expect(published('x-foo'), ['Foo', 'baz']);
+    expect(published('x-bar'), ['Foo', 'baz', 'Bar']);
+    expect(published('x-zot'), ['Foo', 'baz', 'Bar', 'zot']);
+    expect(published('x-squid'), ['Foo', 'baz', 'Bar', 'zot', 'squid']);
+  });
+}
diff --git a/pkg/polymer/test/publish_attributes_test.html b/pkg/polymer/test/publish_attributes_test.html
new file mode 100644
index 0000000..6b9347a
--- /dev/null
+++ b/pkg/polymer/test/publish_attributes_test.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <head>
+    <title>publish attributes</title>
+    <script src="packages/polymer/boot.js"></script>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+    <polymer-element name="x-foo" attributes="Foo baz">
+    </polymer-element>
+
+    <polymer-element name="x-bar" extends="x-foo" attributes="Bar">
+    </polymer-element>
+
+    <polymer-element name="x-zot" extends="x-bar">
+    </polymer-element>
+
+    <polymer-element name="x-squid" extends="x-zot" attributes="squid">
+    </polymer-element>
+
+  <script type="application/dart" src="publish_attributes_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/test/take_attributes_test.dart b/pkg/polymer/test/take_attributes_test.dart
new file mode 100644
index 0000000..a9e409f
--- /dev/null
+++ b/pkg/polymer/test/take_attributes_test.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('x-foo')
+class XFoo extends PolymerElement {
+  @published bool boolean = false;
+  @published num number = 42;
+  @published String str = "don't panic";
+}
+
+@CustomTag('x-bar')
+class XBar extends PolymerElement {
+  @observable bool boolean = false;
+  @observable num number = 42;
+  @observable String str = "don't panic";
+}
+
+@CustomTag('x-zot')
+class XZot extends XBar {
+  @observable num number = 84;
+}
+
+@CustomTag('x-date')
+class XDate extends PolymerElement {
+  @observable var value = new DateTime(2013, 9, 25);
+}
+
+@CustomTag('x-array')
+class XArray extends PolymerElement {
+  @observable List values;
+}
+
+@CustomTag('x-obj')
+class XObj extends PolymerElement {
+  @observable var values = {};
+}
+
+main() {
+  useHtmlConfiguration();
+
+  test('take attributes', () {
+    queryXTag(x) => document.query(x).xtag;
+
+    expect(queryXTag("#foo0").boolean, true);
+    expect(queryXTag("#foo1").boolean, false);
+    expect(queryXTag("#foo2").boolean, true);
+    expect(queryXTag("#foo3").boolean, false);
+    // this one is only 'truthy'
+    expect(queryXTag("#foo4").boolean, true);
+    // this one is also 'truthy', but should it be?
+    expect(queryXTag("#foo5").boolean, true);
+    //
+    expect(queryXTag("#foo0").number, 42);
+    expect(queryXTag("#foo0").str, "don't panic");
+    //
+    expect(queryXTag("#bar0").boolean, true);
+    expect(queryXTag("#bar1").boolean, false);
+    expect(queryXTag("#bar2").boolean, true);
+    expect(queryXTag("#bar3").boolean, false);
+    // this one is only 'truthy'
+    expect(queryXTag("#bar4").boolean, true);
+    // this one is also 'truthy', but should it be?
+    expect(queryXTag("#bar5").boolean, true);
+    //
+    expect(queryXTag("#bar0").number, 42);
+    expect(queryXTag("#bar0").str, "don't panic");
+    //
+    expect(queryXTag("#zot0").boolean, true);
+    expect(queryXTag("#zot1").boolean, false);
+    expect(queryXTag("#zot2").boolean, true);
+    expect(queryXTag("#zot3").boolean, false);
+    // this one is only 'truthy'
+    expect(queryXTag("#zot4").boolean, true);
+    // this one is also 'truthy', but should it be?
+    expect(queryXTag("#zot5").boolean, true);
+    //
+    expect(queryXTag("#zot0").number, 84);
+    expect(queryXTag("#zot6").number, 185);
+    expect(queryXTag("#zot0").str, "don't panic");
+    //
+    // Date deserialization tests
+    expect(queryXTag("#date1").value, new DateTime(2014, 12, 25));
+    expect(queryXTag("#date2").value, isNot(equals(new DateTime(2014, 12, 25))),
+        reason: 'Dart does not support this format');
+    expect(queryXTag("#date3").value, new DateTime(2014, 12, 25, 11, 45));
+    expect(queryXTag("#date4").value, new DateTime(2014, 12, 25, 11, 45, 30));
+    // Failures on Firefox. Need to fix this with custom parsing
+    //expect(String(queryXTag("#date5").value), String(new Date(2014, 11, 25, 11, 45, 30)));
+    //
+    // milliseconds in the Date string not supported on Firefox
+    //expect(queryXTag("#date5").value.getMilliseconds(), new Date(2014, 11, 25, 11, 45, 30, 33).getMilliseconds());
+    //
+    // Array deserialization tests
+    expect(queryXTag("#arr1").values, [0, 1, 2]);
+    expect(queryXTag("#arr2").values, [33]);
+    // Object deserialization tests
+    expect(queryXTag("#obj1").values, { 'name': 'Brandon',
+        'nums': [1, 22, 33] });
+    expect(queryXTag("#obj2").values, { "color": "Red" });
+    expect(queryXTag("#obj3").values, { 'movie': 'Buckaroo Banzai',
+        'DOB': '07/31/1978' });
+  });
+}
diff --git a/pkg/polymer/test/take_attributes_test.html b/pkg/polymer/test/take_attributes_test.html
new file mode 100644
index 0000000..c65f604
--- /dev/null
+++ b/pkg/polymer/test/take_attributes_test.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <head>
+    <title>take attributes</title>
+    <script src="packages/polymer/boot.js"></script>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+    <polymer-element name="x-foo"></polymer-element>
+
+    <x-foo id="foo0" boolean="true"></x-foo>
+    <x-foo id="foo1" boolean="false"></x-foo>
+    <x-foo id="foo2" boolean></x-foo>
+    <x-foo id="foo3"></x-foo>
+    <x-foo id="foo4" boolean="squid"></x-foo>
+    <x-foo id="foo5" boolean="0"></x-foo>
+
+    <polymer-element name="x-bar" attributes="boolean number str">
+    </polymer-element>
+
+    <x-bar id="bar0" boolean="true"></x-bar>
+    <x-bar id="bar1" boolean="false"></x-bar>
+    <x-bar id="bar2" boolean></x-bar>
+    <x-bar id="bar3"></x-bar>
+    <x-bar id="bar4" boolean="squid"></x-bar>
+    <x-bar id="bar5" boolean="0"></x-bar>
+
+    <polymer-element name="x-zot" extends="x-bar" attributes="boolean">
+    </polymer-element>
+
+    <x-zot id="zot0" boolean="true"></x-zot>
+    <x-zot id="zot1" boolean="false"></x-zot>
+    <x-zot id="zot2" boolean></x-zot>
+    <x-zot id="zot3"></x-zot>
+    <x-zot id="zot4" boolean="squid"></x-zot>
+    <x-zot id="zot5" boolean="0"></x-zot>
+    <x-zot id="zot6" number="185"></x-zot>
+
+    <polymer-element name="x-date" attributes="value"></polymer-element>
+
+    <!--
+    TODO(jmesserly): Dart note: I changed these to dash "-" instead of slash "/"
+    as the year-month-day separator. Also the form "December 25, 2014" is not
+    supported in Dart.
+    -->
+    <x-date id="date1" value="2014-12-25"></x-date>
+    <x-date id="date2" value="December 25, 2014"></x-date>
+    <x-date id="date3" value="2014-12-25 11:45"></x-date>
+    <x-date id="date4" value="2014-12-25 11:45:30"></x-date>
+    <x-date id="date5" value="2014-12-25 11:45:30:33"></x-date>
+    <x-date id="dated" value="2014-12-25T11:45:30:33"></x-date>
+
+    <polymer-element name="x-array" attributes="values"></polymer-element>
+
+    <x-array id="arr1" values="[0, 1, 2]"></x-array>
+    <x-array id="arr2" values="[33]"></x-array>
+
+    <polymer-element name="x-obj" attributes="values"></polymer-element>
+
+    <x-obj id="obj1" values='{ "name": "Brandon", "nums": [1, 22, 33] }'>
+    </x-obj>
+    <x-obj id="obj2" values='{ "color": "Red" }'></x-obj>
+    <x-obj id="obj3"
+           values="{ 'movie': 'Buckaroo Banzai', 'DOB': '07/31/1978' }">
+    </x-obj>
+
+  <script type="application/dart" src="take_attributes_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer_expressions/lib/expression.dart b/pkg/polymer_expressions/lib/expression.dart
index 0a5bb82..60b7548 100644
--- a/pkg/polymer_expressions/lib/expression.dart
+++ b/pkg/polymer_expressions/lib/expression.dart
@@ -8,7 +8,7 @@
 
 // Helper functions for building expression trees programmatically
 
-EmptyExpression empty() => new EmptyExpression();
+EmptyExpression empty() => const EmptyExpression();
 Literal literal(v) => new Literal(v);
 MapLiteral mapLiteral(List<MapLiteralEntry> entries) => new MapLiteral(entries);
 MapLiteralEntry mapLiteralEntry(Literal key, Expression value) =>
@@ -24,7 +24,7 @@
 
 
 class AstFactory {
-  EmptyExpression empty() => new EmptyExpression();
+  EmptyExpression empty() => const EmptyExpression();
 
   Literal literal(v) => new Literal(v);
 
@@ -52,12 +52,13 @@
 
 /// Base class for all expressions
 abstract class Expression {
+  const Expression();
   accept(Visitor v);
 }
 
 class EmptyExpression extends Expression {
+  const EmptyExpression();
   accept(Visitor v) => v.visitEmptyExpression(this);
-  bool operator ==(o) => o is EmptyExpression;
 }
 
 class Literal<T> extends Expression {
diff --git a/pkg/scheduled_test/lib/scheduled_process.dart b/pkg/scheduled_test/lib/scheduled_process.dart
index 4b28309..b0ceaa3 100644
--- a/pkg/scheduled_test/lib/scheduled_process.dart
+++ b/pkg/scheduled_test/lib/scheduled_process.dart
@@ -17,7 +17,9 @@
 /// synchronously. All operations on this class are scheduled.
 ///
 /// Before running the test, either [shouldExit] or [kill] must be called on
-/// this to ensure that the process terminates when expected.
+/// this to ensure that the process terminates when expected. Note that [kill]
+/// is using SIGKILL, to ensure the process is killed on Mac OS X (an early
+/// SIGTERM on Mac OS X may be ignored).
 ///
 /// If the test fails, this will automatically print out any stdout and stderr
 /// from the process to aid debugging.
@@ -220,7 +222,7 @@
       if (!_exitCode.hasValue) {
         killedPrematurely = true;
         _endExpected = true;
-        _process.value.kill();
+        _process.value.kill(ProcessSignal.SIGKILL);
         // Ensure that the onException queue waits for the process to actually
         // exit after being killed.
         wrapFuture(_process.value.exitCode, "waiting for process "
@@ -328,7 +330,9 @@
     _taskBeforeEnd = currentSchedule.tasks.contents.last;
     schedule(() {
       _endExpected = true;
-      return _process.then((p) => p.kill()).then((_) => _exitCode);
+      return _process
+          .then((p) => p.kill(ProcessSignal.SIGKILL))
+          .then((_) => _exitCode);
     }, "waiting for process '$description' to die");
   }
 
diff --git a/pkg/unittest/lib/html_config.dart b/pkg/unittest/lib/html_config.dart
index e4eba0f..860ec4f 100644
--- a/pkg/unittest/lib/html_config.dart
+++ b/pkg/unittest/lib/html_config.dart
@@ -10,6 +10,7 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:html';
+import 'dart:js' as js;
 import 'unittest.dart';
 
 /** Creates a table showing tests results in HTML. */
@@ -100,7 +101,12 @@
   void _installHandlers() {
     if (_onErrorSubscription == null) {
       _onErrorSubscription = window.onError.listen(
-        (e) => handleExternalError(e, '(DOM callback has errors)'));
+        (e) {
+          // Some tests may expect this and have no way to suppress the error.
+          if (js.context['testExpectsGlobalError'] != true) {
+            handleExternalError(e, '(DOM callback has errors)');
+          }
+        });
     }
     if (_onMessageSubscription == null) {
       _onMessageSubscription = window.onMessage.listen(
diff --git a/pkg/unittest/lib/test_controller.js b/pkg/unittest/lib/test_controller.js
index 4862e03..7cf6699 100644
--- a/pkg/unittest/lib/test_controller.js
+++ b/pkg/unittest/lib/test_controller.js
@@ -11,9 +11,20 @@
 if (typeof console == "object" && typeof console.clear == "function") {
   console.clear();
 }
+
+// Some tests may expect and have no way to suppress global errors.
+var testExpectsGlobalError = false;
+var testSuppressedGlobalErrors = [];
+
 // Set window onerror to make sure that we catch test harness errors across all
 // browsers.
 window.onerror = function (message, url, lineNumber) {
+  if (testExpectsGlobalError) {
+    testSuppressedGlobalErrors.push({
+      message: message
+    });
+    return;
+  }
   if (url) {
     showErrorAndExit(
         "\n\n" + url + ":" + lineNumber + ":\n" + message + "\n\n");
@@ -67,7 +78,7 @@
 
   // TODO(ricow): REMOVE, debug info, see issue 13292
   if (!testRunner) {
-    dartPrint('Calling notifyDone()');
+    printMessage('Calling notifyDone()');
   }
   // To support in browser launching of tests we post back start and result
   // messages to the window.opener.
@@ -80,7 +91,7 @@
 function processMessage(msg) {
   // TODO(ricow): REMOVE, debug info, see issue 13292
   if (!testRunner) {
-    dartPrint('processMessage(): ' + msg);
+    printMessage('processMessage(): ' + msg);
   }
   if (typeof msg != 'string') return;
   if (msg == 'unittest-suite-done') {
@@ -95,7 +106,7 @@
       window.postMessage('unittest-suite-success', '*');
     }
   } else if (msg == 'unittest-suite-success') {
-    dartPrint('PASS');
+    printMessage('PASS');
     notifyDone();
   } else if (msg == 'unittest-suite-fail') {
     showErrorAndExit('Some tests failed.');
@@ -114,11 +125,11 @@
 
 function showErrorAndExit(message) {
   if (message) {
-    dartPrint('Error: ' + String(message));
+    printMessage('Error: ' + String(message));
   }
   // dart/tools/testing/run_selenium.py is looking for either PASS or
   // FAIL and will continue polling until one of these words show up.
-  dartPrint('FAIL');
+  printMessage('FAIL');
   notifyDone();
 }
 
@@ -158,27 +169,50 @@
 });
 
 // dart2js will generate code to call this function to handle the Dart
-// [print] method. The base [Configuration] (config.html) calls
-// [print] with the secret messages "unittest-suite-success" and
-// "unittest-suite-wait-for-done". These messages are then posted so
-// processMessage above will see them.
+// [print] method.
+//
+// dartium will invoke this method for [print] calls if the environment variable
+// "DART_FORWARDING_PRINT" was set when launching dartium.
+//
+// Our tests will be wrapped, so we can detect when [main] is called and when
+// it has ended.
+// The wrapping happens either via "dartMainRunner" (for dart2js) or wrapped
+// tests for dartium.
+//
+// The following messages are handled specially:
+//   dart-calling-main:  signals that the dart [main] function will be invoked
+//   dart-main-done:  signals that the dart [main] function has finished
+//   unittest-suite-wait-for-done:  signals the start of an asynchronous test
+//   unittest-suite-success:  signals the end of an asynchrounous test
+//
+// These messages are used to communicate with the test and will be posted so
+// [processMessage] above can see it.
 function dartPrint(msg) {
   if ((msg === 'unittest-suite-success')
       || (msg === 'unittest-suite-done')
-      || (msg === 'unittest-suite-wait-for-done')) {
+      || (msg === 'unittest-suite-wait-for-done')
+      || (msg === 'dart-calling-main')
+      || (msg === 'dart-main-done')) {
     window.postMessage(msg, '*');
     return;
   }
+  printMessage(msg);
+}
+
+// Prints 'msg' to the console (if available) and to the body of the html
+// document.
+function printMessage(msg) {
   if (typeof console === 'object') console.warn(msg);
-  var pre = document.createElement("pre");
+  var pre = document.createElement('pre');
   pre.appendChild(document.createTextNode(String(msg)));
   document.body.appendChild(pre);
+  document.body.appendChild(document.createTextNode('\n'));
 }
 
 // dart2js will generate code to call this function instead of calling
 // Dart [main] directly. The argument is a closure that invokes main.
 function dartMainRunner(main) {
-  window.postMessage('dart-calling-main', '*');
+  dartPrint('dart-calling-main');
   try {
     main();
   } catch (e) {
@@ -187,5 +221,5 @@
     window.postMessage('unittest-suite-fail', '*');
     return;
   }
-  window.postMessage('dart-main-done', '*');
+  dartPrint('dart-main-done');
 }
diff --git a/pkg/unittest/lib/vm_config.dart b/pkg/unittest/lib/vm_config.dart
index 962ca97..e37cf72 100644
--- a/pkg/unittest/lib/vm_config.dart
+++ b/pkg/unittest/lib/vm_config.dart
@@ -21,8 +21,9 @@
   // We make this public so the user can turn it off if they want.
   bool useColor;
 
-  VMConfiguration() :
-    super(), useColor = stdioType(stdout) == StdioType.TERMINAL;
+  VMConfiguration()
+      : super(),
+        useColor = stdioType(stdout) == StdioType.TERMINAL;
 
   String formatResult(TestCase testCase) {
     String result = super.formatResult(testCase);
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 182f2ff..2486c5b 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -35,7 +35,7 @@
     Dart_Handle patch_file_uri = DartUtils::NewString(patch_filename);
     free(patch_filename);
 
-    DART_CHECK_VALID(Dart_LoadPatch(library, patch_file_uri, patch_src));
+    DART_CHECK_VALID(Dart_LibraryLoadPatch(library, patch_file_uri, patch_src));
   }
 }
 
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 07cc545..48c10fb 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -13,6 +13,7 @@
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 #include "bin/io_natives.h"
+#include "bin/platform.h"
 
 namespace dart {
 namespace bin {
@@ -26,7 +27,7 @@
   V(Directory_Create, 1)                                                       \
   V(Directory_Current, 0)                                                      \
   V(Directory_SetCurrent, 1)                                                   \
-  V(Directory_CreateTemp, 1)                                                   \
+  V(Directory_CreateTemp, 2)                                                   \
   V(Directory_Delete, 2)                                                       \
   V(Directory_Rename, 2)                                                       \
   V(Directory_List, 3)                                                         \
@@ -108,12 +109,10 @@
     // an isolate gets interrupted by the embedder in the middle of
     // Dart_StringToUTF8?  We need to make sure not to swallow the
     // interrupt.
-    fputs(Dart_GetError(result), stdout);
+    Platform::PrintBlocking(stdout, "%s\n", Dart_GetError(result));
   } else {
-    fwrite(chars, sizeof(*chars), length, stdout);
+    Platform::PrintBlocking(stdout, "%.*s\n", static_cast<int>(length), chars);
   }
-  fputc('\n', stdout);
-  fflush(stdout);
 }
 
 }  // namespace bin
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 323b4a9..6aa4d09 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -78,7 +78,14 @@
 
 void FUNCTION_NAME(Directory_CreateTemp)(Dart_NativeArguments args) {
   Dart_Handle path = Dart_GetNativeArgument(args, 0);
-  char* result = Directory::CreateTemp(DartUtils::GetStringValue(path));
+  Dart_Handle system = Dart_GetNativeArgument(args, 1);
+  if (!Dart_IsString(path)) {
+    Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(
+        "Template argument of CreateSystemTempSync is not a String"));
+    return;
+  }
+  char* result = Directory::CreateTemp(DartUtils::GetStringValue(path),
+                                       DartUtils::GetBooleanValue(system));
   if (result != NULL) {
     Dart_SetReturnValue(args, DartUtils::NewString(result));
     free(result);
@@ -188,7 +195,7 @@
 CObject* Directory::CreateTempRequest(const CObjectArray& request) {
   if (request.Length() == 1 && request[0]->IsString()) {
     CObjectString path(request[0]);
-    char* result = Directory::CreateTemp(path.CString());
+    char* result = Directory::CreateTemp(path.CString(), false);
     if (result != NULL) {
       CObject* temp_dir = new CObjectString(CObject::NewString(result));
       free(result);
@@ -200,6 +207,23 @@
   return CObject::IllegalArgumentError();
 }
 
+
+CObject* Directory::CreateSystemTempRequest(const CObjectArray& request) {
+  if (request.Length() == 1 && request[0]->IsString()) {
+    CObjectString path(request[0]);
+    char* result = Directory::CreateTemp(path.CString(), true);
+    if (result != NULL) {
+      CObject* temp_dir = new CObjectString(CObject::NewString(result));
+      free(result);
+      return temp_dir;
+    } else {
+      return CObject::NewOSError();
+    }
+  }
+  return CObject::IllegalArgumentError();
+}
+
+
 static CObject* CreateIllegalArgumentError() {
   // Respond with an illegal argument list error message.
   CObjectArray* error = new CObjectArray(CObject::NewArray(3));
@@ -210,6 +234,7 @@
   return error;
 }
 
+
 CObject* Directory::ListStartRequest(const CObjectArray& request) {
   if (request.Length() == 3 &&
       request[0]->IsString() &&
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index 210739e..57302a2 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -252,25 +252,12 @@
     DOES_NOT_EXIST
   };
 
-  // This enum must be kept in sync with the request values in
-  // directory_impl.dart.
-  enum DirectoryRequest {
-    kCreateRequest = 0,
-    kDeleteRequest = 1,
-    kExistsRequest = 2,
-    kCreateTempRequest = 3,
-    kListStartRequest = 4,
-    kListNextRequest = 5,
-    kListStopRequest = 6,
-    kRenameRequest = 7
-  };
-
   static void List(DirectoryListing* listing);
   static ExistsResult Exists(const char* path);
   static char* Current();
   static bool SetCurrent(const char* path);
   static bool Create(const char* path);
-  static char* CreateTemp(const char* const_template);
+  static char* CreateTemp(const char* const_template, bool system);
   static bool Delete(const char* path, bool recursive);
   static bool Rename(const char* path, const char* new_path);
 
@@ -278,6 +265,7 @@
   static CObject* DeleteRequest(const CObjectArray& request);
   static CObject* ExistsRequest(const CObjectArray& request);
   static CObject* CreateTempRequest(const CObjectArray& request);
+  static CObject* CreateSystemTempRequest(const CObjectArray& request);
   static CObject* ListStartRequest(const CObjectArray& request);
   static CObject* ListNextRequest(const CObjectArray& request);
   static CObject* ListStopRequest(const CObjectArray& request);
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index b48474d..6a2646a 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -382,33 +382,34 @@
 }
 
 
-char* Directory::CreateTemp(const char* const_template) {
+char* Directory::CreateTemp(const char* const_template, bool system) {
   // Returns a new, unused directory name, modifying the contents of
   // dir_template.  Creates the directory with the permissions specified
   // by the process umask.
   // The return value must be freed by the caller.
   PathBuffer path;
-  path.Add(const_template);
-  if (path.length() == 0) {
+  if (system) {
     // Android does not have a /tmp directory. A partial substitute,
     // suitable for bring-up work and tests, is to create a tmp
     // directory in /data/local/tmp.
     //
     // TODO(4413): In the long run, when running in an application we should
-    // probably use android.content.Context.getCacheDir().
+    // probably use the appropriate directory from the Android API,
+    // probably what File.createTempFile uses.
     #define ANDROID_TEMP_DIR "/data/local/tmp"
     struct stat st;
     if (stat(ANDROID_TEMP_DIR, &st) != 0) {
       mkdir(ANDROID_TEMP_DIR, 0777);
     }
-    path.Add(ANDROID_TEMP_DIR "/temp_dir1_");
-  } else if ((path.AsString())[path.length() - 1] == '/') {
-    path.Add("temp_dir_");
+    path.Add(ANDROID_TEMP_DIR "/");
   }
+
+  path.Add(const_template);
   if (!path.Add("XXXXXX")) {
     // Pattern has overflowed.
     return NULL;
   }
+
   char* result;
   do {
     result = MakeTempDirectory(path.AsString());
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index 88c6f7c..e12dbfd 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -9,6 +9,7 @@
 
 #include <dirent.h>  // NOLINT
 #include <errno.h>  // NOLINT
+#include <stdlib.h>  // NOLINT
 #include <string.h>  // NOLINT
 #include <sys/param.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
@@ -372,18 +373,27 @@
 }
 
 
-char* Directory::CreateTemp(const char* const_template) {
+char* Directory::CreateTemp(const char* const_template, bool system) {
   // Returns a new, unused directory name, modifying the contents of
   // dir_template.  Creates the directory with the permissions specified
   // by the process umask.
   // The return value must be freed by the caller.
   PathBuffer path;
-  path.Add(const_template);
-  if (path.length() == 0) {
-    path.Add("/tmp/temp_dir1_");
-  } else if ((path.AsString())[path.length() - 1] == '/') {
-    path.Add("temp_dir_");
+  if (system) {
+    const char* temp_dir = getenv("TMPDIR");
+    if (temp_dir == NULL) {
+      temp_dir = getenv("TMP");
+    }
+    if (temp_dir != NULL) {
+      path.Add(temp_dir);
+      if (temp_dir[strlen(temp_dir) - 1] != '/') {
+        path.Add("/");
+      }
+    } else {
+      path.Add("/tmp/");
+    }
   }
+  path.Add(const_template);
   if (!path.Add("XXXXXX")) {
     // Pattern has overflowed.
     return NULL;
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index 08232d5..5757a9c 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -361,18 +361,27 @@
 }
 
 
-char* Directory::CreateTemp(const char* const_template) {
+char* Directory::CreateTemp(const char* const_template, bool system) {
   // Returns a new, unused directory name, modifying the contents of
   // dir_template.  Creates the directory with the permissions specified
   // by the process umask.
   // The return value must be freed by the caller.
   PathBuffer path;
-  path.Add(const_template);
-  if (path.length() == 0) {
-    path.Add("/tmp/temp_dir1_");
-  } else if ((path.AsString())[path.length() - 1] == '/') {
-    path.Add("temp_dir_");
+  if (system) {
+    const char* temp_dir = getenv("TMPDIR");
+    if (temp_dir == NULL) {
+      temp_dir = getenv("TMP");
+    }
+    if (temp_dir != NULL) {
+      path.Add(temp_dir);
+      if (temp_dir[strlen(temp_dir) - 1] != '/') {
+        path.Add("/");
+      }
+    } else {
+      path.Add("/tmp/");
+    }
   }
+  path.Add(const_template);
   if (!path.Add("XXXXXX")) {
     // Pattern has overflowed.
     return NULL;
diff --git a/runtime/bin/directory_patch.dart b/runtime/bin/directory_patch.dart
index da4e014..f5961b9 100644
--- a/runtime/bin/directory_patch.dart
+++ b/runtime/bin/directory_patch.dart
@@ -5,7 +5,8 @@
 patch class _Directory {
   /* patch */ static _current() native "Directory_Current";
   /* patch */ static _setCurrent(path) native "Directory_SetCurrent";
-  /* patch */ static _createTemp(String template) native "Directory_CreateTemp";
+  /* patch */ static _createTemp(String template, bool system)
+      native "Directory_CreateTemp";
   /* patch */ static int _exists(String path) native "Directory_Exists";
   /* patch */ static _create(String path) native "Directory_Create";
   /* patch */ static _deleteNative(String path, bool recursive)
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index f5f77bd..c72f4ef 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -383,30 +383,26 @@
 }
 
 
-char* Directory::CreateTemp(const char* const_template) {
+char* Directory::CreateTemp(const char* const_template, bool system) {
   // Returns a new, unused directory name, modifying the contents of
   // dir_template.  Creates this directory, with a default security
   // descriptor inherited from its parent directory.
   // The return value must be freed by the caller.
   PathBuffer path;
-  if (0 == strncmp(const_template, "", 1)) {
+  if (system) {
     path.Reset(GetTempPathW(MAX_PATH, path.AsStringW()));
     if (path.length() == 0) {
       return NULL;
     }
-  } else {
-    const wchar_t* system_template = StringUtils::Utf8ToWide(const_template);
-    path.AddW(system_template);
-    free(const_cast<wchar_t*>(system_template));
   }
-  // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44.
-  if (path.length() > MAX_PATH - 44) {
+  const wchar_t* system_template = StringUtils::Utf8ToWide(const_template);
+  path.AddW(system_template);
+  free(const_cast<wchar_t*>(system_template));
+
+  // Length of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 36.
+  if (path.length() > MAX_PATH - 36) {
     return NULL;
   }
-  if ((path.AsStringW())[path.length() - 1] == L'\\') {
-    // No base name for the directory - use "tempdir".
-    path.AddW(L"tempdir");
-  }
 
   UUID uuid;
   RPC_STATUS status = UuidCreateSequential(&uuid);
@@ -419,7 +415,6 @@
     return NULL;
   }
 
-  path.AddW(L"-");
   // RPC_WSTR is an unsigned short*, so we cast to wchar_t*.
   path.AddW(reinterpret_cast<wchar_t*>(uuid_string));
   RpcStringFreeW(&uuid_string);
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 59b2207..51e98ac 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -7,7 +7,6 @@
 
 #include "bin/eventhandler.h"
 
-#include <process.h>  // NOLINT
 #include <winsock2.h>  // NOLINT
 #include <ws2tcpip.h>  // NOLINT
 #include <mswsock.h>  // NOLINT
@@ -19,7 +18,7 @@
 #include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/utils.h"
-#include "platform/thread.h"
+#include "vm/thread.h"
 
 
 namespace dart {
@@ -107,7 +106,6 @@
       pending_read_(NULL),
       pending_write_(NULL),
       last_error_(NOERROR),
-      thread_wrote_(0),
       flags_(0) {
   InitializeCriticalSection(&cs_);
 }
@@ -123,7 +121,6 @@
       pending_read_(NULL),
       pending_write_(NULL),
       last_error_(NOERROR),
-      thread_wrote_(0),
       flags_(0) {
   InitializeCriticalSection(&cs_);
 }
@@ -211,10 +208,9 @@
 }
 
 
-static unsigned int __stdcall ReadFileThread(void* args) {
+static void ReadFileThread(uword args) {
   Handle* handle = reinterpret_cast<Handle*>(args);
   handle->ReadSyncCompleteAsync();
-  return 0;
 }
 
 
@@ -273,11 +269,10 @@
   } else {
     // Completing asynchronously through thread.
     pending_read_ = buffer;
-    uint32_t tid;
-    uintptr_t thread_handle =
-        _beginthreadex(NULL, 32 * 1024, ReadFileThread, this, 0, &tid);
-    if (thread_handle == -1) {
-      FATAL("Failed to start read file thread");
+    int result = dart::Thread::Start(ReadFileThread,
+                                     reinterpret_cast<uword>(this));
+    if (result != 0) {
+      FATAL1("Failed to start read file thread %d", result);
     }
     return true;
   }
@@ -333,18 +328,6 @@
 }
 
 
-void FileHandle::DoClose() {
-  if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) {
-    int fd = _open("NUL", _O_WRONLY);
-    ASSERT(fd >= 0);
-    _dup2(fd, _fileno(stdout));
-    close(fd);
-  } else {
-    Handle::DoClose();
-  }
-}
-
-
 void DirectoryWatchHandle::EnsureInitialized(
     EventHandlerImplementation* event_handler) {
   ScopedLock lock(this);
@@ -560,14 +543,46 @@
 }
 
 
-static unsigned int __stdcall WriteFileThread(void* args) {
-  Handle* handle = reinterpret_cast<Handle*>(args);
-  handle->WriteSyncCompleteAsync();
-  return 0;
+int Handle::Write(const void* buffer, int num_bytes) {
+  ScopedLock lock(this);
+  if (pending_write_ != NULL) return 0;
+  if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+  ASSERT(SupportsOverlappedIO());
+  if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
+  pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
+  pending_write_->Write(buffer, num_bytes);
+  if (!IssueWrite()) return -1;
+  return num_bytes;
 }
 
 
-void Handle::WriteSyncCompleteAsync() {
+static void WriteFileThread(uword args) {
+  StdHandle* handle = reinterpret_cast<StdHandle*>(args);
+  handle->RunWriteLoop();
+}
+
+
+void StdHandle::RunWriteLoop() {
+  write_monitor_->Enter();
+  write_thread_running_ = true;
+  // Notify we have started.
+  write_monitor_->Notify();
+
+  while (write_thread_running_) {
+    write_monitor_->Wait(Monitor::kNoTimeout);
+    if (pending_write_ != NULL) {
+      // We woke up and had a pending write. Execute it.
+      WriteSyncCompleteAsync();
+    }
+  }
+
+  write_thread_exists_ = false;
+  write_monitor_->Notify();
+  write_monitor_->Exit();
+}
+
+
+void StdHandle::WriteSyncCompleteAsync() {
   ASSERT(pending_write_ != NULL);
 
   DWORD bytes_written = -1;
@@ -593,39 +608,57 @@
   }
 }
 
-
-int Handle::Write(const void* buffer, int num_bytes) {
+int StdHandle::Write(const void* buffer, int num_bytes) {
   ScopedLock lock(this);
   if (pending_write_ != NULL) return 0;
   if (num_bytes > kBufferSize) num_bytes = kBufferSize;
-  if (SupportsOverlappedIO()) {
-    if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
-    pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
-    pending_write_->Write(buffer, num_bytes);
-    if (!IssueWrite()) return -1;
+  // In the case of stdout and stderr, OverlappedIO is not supported.
+  // Here we'll instead use a thread, to make it async.
+  // This code is actually never exposed to the user, as stdout and stderr is
+  // not available as a RawSocket, but only wrapped in a Socket.
+  // Note that we return '0', unless a thread have already completed a write.
+  MonitorLocker locker(write_monitor_);
+  if (thread_wrote_ > 0) {
+    if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
+    thread_wrote_ -= num_bytes;
     return num_bytes;
+  }
+  if (!write_thread_exists_) {
+    write_thread_exists_ = true;
+    int result = dart::Thread::Start(WriteFileThread,
+                                     reinterpret_cast<uword>(this));
+    if (result != 0) {
+      FATAL1("Failed to start write file thread %d", result);
+    }
+    while (!write_thread_running_) {
+      // Wait until we the thread is running.
+      locker.Wait(Monitor::kNoTimeout);
+    }
+  }
+  // Create buffer and notify thread about the new handle.
+  pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
+  pending_write_->Write(buffer, num_bytes);
+  locker.Notify();
+  return 0;
+}
+
+
+void StdHandle::DoClose() {
+  MonitorLocker locker(write_monitor_);
+  if (write_thread_exists_) {
+    write_thread_running_ = false;
+    locker.Notify();
+    while (write_thread_exists_) {
+      locker.Wait(Monitor::kNoTimeout);
+    }
+  }
+  if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) {
+    int fd = _open("NUL", _O_WRONLY);
+    ASSERT(fd >= 0);
+    _dup2(fd, _fileno(stdout));
+    close(fd);
   } else {
-    // In the case of stdout and stderr, OverlappedIO is not supported.
-    // Here we'll instead spawn a new thread for each write, to make it async.
-    // This code is actually never exposed to the user, as stdout and stderr is
-    // not available as a RawSocket, but only wrapped in a Socket.
-    // Note that we return '0', unless a thread have already completed a write.
-    // TODO(ajohnsen): Don't spawn a new thread per write. Issue 13541.
-    if (thread_wrote_ > 0) {
-      if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
-      thread_wrote_ -= num_bytes;
-      return num_bytes;
-    }
-    pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
-    pending_write_->Write(buffer, num_bytes);
-    // Completing asynchronously through thread.
-    uint32_t tid;
-    uintptr_t thread_handle =
-        _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid);
-    if (thread_handle == -1) {
-      FATAL("Failed to start write file thread");
-    }
-    return 0;
+    Handle::DoClose();
   }
 }
 
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index 945277b..43562cd 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -13,6 +13,7 @@
 #include <mswsock.h>
 
 #include "bin/builtin.h"
+#include "platform/thread.h"
 
 
 namespace dart {
@@ -132,6 +133,7 @@
  public:
   enum Type {
     kFile,
+    kStd,
     kDirectoryWatch,
     kClientSocket,
     kListenSocket
@@ -156,7 +158,7 @@
   // Socket interface exposing normal socket operations.
   int Available();
   int Read(void* buffer, int num_bytes);
-  int Write(const void* buffer, int num_bytes);
+  virtual int Write(const void* buffer, int num_bytes);
 
   // Internal interface used by the event handler.
   virtual bool IssueRead();
@@ -211,7 +213,6 @@
   }
 
   void ReadSyncCompleteAsync();
-  void WriteSyncCompleteAsync();
 
   DWORD last_error() { return last_error_; }
   void set_last_error(DWORD last_error) { last_error_ = last_error; }
@@ -242,7 +243,6 @@
   OverlappedBuffer* pending_write_;  // Buffer for pending write
 
   DWORD last_error_;
-  DWORD thread_wrote_;
 
  private:
   int flags_;
@@ -259,7 +259,35 @@
 
   virtual void EnsureInitialized(EventHandlerImplementation* event_handler);
   virtual bool IsClosed();
+};
+
+
+class StdHandle : public FileHandle {
+ public:
+  explicit StdHandle(HANDLE handle)
+      : FileHandle(handle),
+        thread_wrote_(0),
+        write_thread_exists_(false),
+        write_thread_running_(false),
+        write_monitor_(new Monitor()) {
+    type_ = kStd;
+  }
+
+  ~StdHandle() {
+    delete write_monitor_;
+  }
+
   virtual void DoClose();
+  virtual int Write(const void* buffer, int num_bytes);
+
+  void WriteSyncCompleteAsync();
+  void RunWriteLoop();
+
+ private:
+  DWORD thread_wrote_;
+  bool write_thread_exists_;
+  bool write_thread_running_;
+  dart::Monitor* write_monitor_;
 };
 
 
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 6eec87a..41efb4c 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -60,35 +60,6 @@
     kOther = 4
   };
 
-  enum FileRequest {
-    kExistsRequest = 0,
-    kCreateRequest = 1,
-    kDeleteRequest = 2,
-    kRenameRequest = 3,
-    kOpenRequest = 4,
-    kResolveSymbolicLinksRequest = 5,
-    kCloseRequest = 6,
-    kPositionRequest = 7,
-    kSetPositionRequest = 8,
-    kTruncateRequest = 9,
-    kLengthRequest = 10,
-    kLengthFromPathRequest = 11,
-    kLastModifiedRequest = 12,
-    kFlushRequest = 13,
-    kReadByteRequest = 14,
-    kWriteByteRequest = 15,
-    kReadRequest = 16,
-    kReadIntoRequest = 17,
-    kWriteFromRequest = 18,
-    kCreateLinkRequest = 19,
-    kDeleteLinkRequest = 20,
-    kRenameLinkRequest = 21,
-    kLinkTargetRequest = 22,
-    kTypeRequest = 23,
-    kIdenticalRequest = 24,
-    kStatRequest = 25
-  };
-
   enum FileStat {
     // These match the constants in FileStat in file_system_entity.dart.
     kType = 0,
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index 014d861..e08c28d 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -49,8 +49,13 @@
   }
   if (events & kModifyContent) list_events |= FILE_NOTIFY_CHANGE_LAST_WRITE;
 
-  return reinterpret_cast<intptr_t>(
-      new DirectoryWatchHandle(dir, list_events, recursive));
+  DirectoryWatchHandle* handle =
+      new DirectoryWatchHandle(dir, list_events, recursive);
+  // Issue a read directly, to be sure events are tracked from now on. This is
+  // okay, since in Dart, we create the socket and start reading immidiately.
+  handle->EnsureInitialized(EventHandler::delegate());
+  handle->IssueRead();
+  return reinterpret_cast<intptr_t>(handle);
 }
 
 
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 0612f15..9f70743 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -143,8 +143,8 @@
 static void WriteSnapshotFile(const uint8_t* buffer, const intptr_t size) {
   File* file = File::Open(snapshot_filename, File::kWriteTruncate);
   ASSERT(file != NULL);
-  for (intptr_t i = 0; i < size; i++) {
-    file->WriteByte(buffer[i]);
+  if (!file->WriteFully(buffer, size)) {
+    Log::PrintErr("Error: Failed to write full snapshot.\n\n");
   }
   delete file;
 }
diff --git a/runtime/bin/io_service.h b/runtime/bin/io_service.h
index 0559039..8c1ba9f 100644
--- a/runtime/bin/io_service.h
+++ b/runtime/bin/io_service.h
@@ -12,6 +12,7 @@
 namespace dart {
 namespace bin {
 
+// This list must be kept in sync with the list in sdk/lib/io/io_service.dart
 #define IO_SERVICE_REQUEST_LIST(V)                                             \
   V(File, Exists, 0)                                                           \
   V(File, Create, 1)                                                           \
@@ -46,11 +47,12 @@
   V(Directory, Delete, 30)                                                     \
   V(Directory, Exists, 31)                                                     \
   V(Directory, CreateTemp, 32)                                                 \
-  V(Directory, ListStart, 33)                                                  \
-  V(Directory, ListNext, 34)                                                   \
-  V(Directory, ListStop, 35)                                                   \
-  V(Directory, Rename, 36)                                                     \
-  V(SSLFilter, ProcessFilter, 37)
+  V(Directory, CreateSystemTemp, 33)                                           \
+  V(Directory, ListStart, 34)                                                  \
+  V(Directory, ListNext, 35)                                                   \
+  V(Directory, ListStop, 36)                                                   \
+  V(Directory, Rename, 37)                                                     \
+  V(SSLFilter, ProcessFilter, 38)
 
 #define DECLARE_REQUEST(type, method, id)                                      \
   k##type##method##Request = id,
@@ -68,4 +70,3 @@
 }  // namespace dart
 
 #endif  // BIN_IO_SERVICE_H_
-
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index ca723ae3..16be960 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -62,6 +62,9 @@
     return argv_;
   }
 
+  static void PrintBlocking(FILE* file, const char* format, ...)
+      PRINTF_ATTRIBUTE(2, 3);
+
  private:
   static const char* executable_name_;
   static const char* package_root_;
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index dfa2e27..445ea01 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -11,6 +11,8 @@
 #include <string.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 
+#include "bin/fdutils.h"
+
 
 namespace dart {
 namespace bin {
@@ -64,6 +66,18 @@
   delete[] env;
 }
 
+
+void Platform::PrintBlocking(FILE* file, const char* format, ...) {
+  int fd = fileno(file);
+  FDUtils::SetBlocking(fd);
+  va_list args;
+  va_start(args, format);
+  vfprintf(file, format, args);
+  fflush(file);
+  va_end(args);
+  FDUtils::SetNonBlocking(fd);
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index af557af..80aa0af 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -11,6 +11,8 @@
 #include <string.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 
+#include "bin/fdutils.h"
+
 
 namespace dart {
 namespace bin {
@@ -64,6 +66,18 @@
   delete[] env;
 }
 
+
+void Platform::PrintBlocking(FILE* file, const char* format, ...) {
+  int fd = fileno(file);
+  FDUtils::SetBlocking(fd);
+  va_list args;
+  va_start(args, format);
+  vfprintf(file, format, args);
+  fflush(file);
+  va_end(args);
+  FDUtils::SetNonBlocking(fd);
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 0576c34..5af6c5a 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -12,6 +12,8 @@
 #include <string.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 
+#include "bin/fdutils.h"
+
 
 namespace dart {
 namespace bin {
@@ -68,6 +70,18 @@
   delete[] env;
 }
 
+
+void Platform::PrintBlocking(FILE* file, const char* format, ...) {
+  int fd = fileno(file);
+  FDUtils::SetBlocking(fd);
+  va_list args;
+  va_start(args, format);
+  vfprintf(file, format, args);
+  fflush(file);
+  va_end(args);
+  FDUtils::SetNonBlocking(fd);
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 85b6694..cd0f0f2 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -64,6 +64,16 @@
   delete[] env;
 }
 
+
+void Platform::PrintBlocking(FILE* file, const char* format, ...) {
+  // No need to set blocking, as it's always blocking on Windows.
+  va_list args;
+  va_start(args, format);
+  vfprintf(file, format, args);
+  fflush(file);
+  va_end(args);
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index d6f9b0d..63fc5ef 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -52,7 +52,7 @@
     ADDRESS_LAST = ADDRESS_ANY_IP_V6,
   };
 
-  explicit SocketAddress(struct sockaddr* sockaddr);
+  explicit SocketAddress(struct sockaddr* sa);
 
   ~SocketAddress() {}
 
@@ -101,9 +101,9 @@
 
 class InterfaceSocketAddress {
  public:
-  explicit InterfaceSocketAddress(struct sockaddr* sockaddr,
+  explicit InterfaceSocketAddress(struct sockaddr* sa,
                                   const char* interface_name)
-      : socket_address_(new SocketAddress(sockaddr)),
+      : socket_address_(new SocketAddress(sa)),
         interface_name_(interface_name) {}
 
   ~InterfaceSocketAddress() {
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 18b2bd8..38c1c7f 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -22,26 +22,19 @@
 namespace dart {
 namespace bin {
 
-SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
+SocketAddress::SocketAddress(struct sockaddr* sa) {
   ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
-  RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
-  const char* result;
-  if (sockaddr->sa_family == AF_INET) {
-    result = inet_ntop(sockaddr->sa_family,
-                       &raw->in.sin_addr,
-                       as_string_,
-                       INET_ADDRSTRLEN);
-  } else {
-    ASSERT(sockaddr->sa_family == AF_INET6);
-    result = inet_ntop(sockaddr->sa_family,
-                       &raw->in6.sin6_addr,
-                       as_string_,
-                       INET6_ADDRSTRLEN);
+  socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa));
+  if (TEMP_FAILURE_RETRY(getnameinfo(sa,
+                                     salen,
+                                     as_string_,
+                                     INET6_ADDRSTRLEN,
+                                     NULL,
+                                     0,
+                                     NI_NUMERICHOST)) != 0) {
+    as_string_[0] = 0;
   }
-  if (result == NULL) as_string_[0] = 0;
-  memmove(reinterpret_cast<void *>(&addr_),
-          sockaddr,
-          GetAddrLength(raw));
+  memmove(reinterpret_cast<void *>(&addr_), sa, salen);
 }
 
 
@@ -157,20 +150,17 @@
     Log::PrintErr("Error getpeername: %s\n", error_message);
     return false;
   }
-  const void* src;
-  if (raw.ss.ss_family == AF_INET6) {
-    src = reinterpret_cast<const void*>(&raw.in6.sin6_addr);
-  } else {
-    src = reinterpret_cast<const void*>(&raw.in.sin_addr);
-  }
-  if (inet_ntop(raw.ss.ss_family,
-                src,
-                host,
-                INET_ADDRSTRLEN) == NULL) {
+  if (TEMP_FAILURE_RETRY(getnameinfo(&raw.addr,
+                                     size,
+                                     host,
+                                     INET6_ADDRSTRLEN,
+                                     NULL,
+                                     0,
+                                     NI_NUMERICHOST)) != 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
     strerror_r(errno, error_message, kBufferSize);
-    Log::PrintErr("Error inet_ntop: %s\n", error_message);
+    Log::PrintErr("Error getnameinfo: %s\n", error_message);
     return false;
   }
   *port = SocketAddress::GetAddrPort(&raw);
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 24e688d..b9431e1 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -23,26 +23,19 @@
 namespace dart {
 namespace bin {
 
-SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
+SocketAddress::SocketAddress(struct sockaddr* sa) {
   ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
-  RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
-  const char* result;
-  if (sockaddr->sa_family == AF_INET) {
-    result = inet_ntop(sockaddr->sa_family,
-                       &raw->in.sin_addr,
-                       as_string_,
-                       INET_ADDRSTRLEN);
-  } else {
-    ASSERT(sockaddr->sa_family == AF_INET6);
-    result = inet_ntop(sockaddr->sa_family,
-                       &raw->in6.sin6_addr,
-                       as_string_,
-                       INET6_ADDRSTRLEN);
+  socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa));
+  if (TEMP_FAILURE_RETRY(getnameinfo(sa,
+                                     salen,
+                                     as_string_,
+                                     INET6_ADDRSTRLEN,
+                                     NULL,
+                                     0,
+                                     NI_NUMERICHOST)) != 0) {
+    as_string_[0] = 0;
   }
-  if (result == NULL) as_string_[0] = 0;
-  memmove(reinterpret_cast<void *>(&addr_),
-          sockaddr,
-          GetAddrLength(raw));
+  memmove(reinterpret_cast<void *>(&addr_), sa, salen);
 }
 
 
@@ -158,19 +151,16 @@
                   strerror_r(errno, error_buf, kBufferSize));
     return false;
   }
-  const void* src;
-  if (raw.ss.ss_family == AF_INET6) {
-    src = reinterpret_cast<const void*>(&raw.in6.sin6_addr);
-  } else {
-    src = reinterpret_cast<const void*>(&raw.in.sin_addr);
-  }
-  if (inet_ntop(raw.ss.ss_family,
-                src,
-                host,
-                INET_ADDRSTRLEN) == NULL) {
+  if (TEMP_FAILURE_RETRY(getnameinfo(&raw.addr,
+                                     size,
+                                     host,
+                                     INET6_ADDRSTRLEN,
+                                     NULL,
+                                     0,
+                                     NI_NUMERICHOST)) != 0) {
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
-    Log::PrintErr("Error inet_ntop: %s\n",
+    Log::PrintErr("Error getnameinfo: %s\n",
                   strerror_r(errno, error_buf, kBufferSize));
     return false;
   }
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 2b6138f..be7beca 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -23,26 +23,19 @@
 namespace dart {
 namespace bin {
 
-SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
+SocketAddress::SocketAddress(struct sockaddr* sa) {
   ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
-  RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
-  const char* result;
-  if (sockaddr->sa_family == AF_INET) {
-    result = inet_ntop(sockaddr->sa_family,
-                       &raw->in.sin_addr,
-                       as_string_,
-                       INET_ADDRSTRLEN);
-  } else {
-    ASSERT(sockaddr->sa_family == AF_INET6);
-    result = inet_ntop(sockaddr->sa_family,
-                       &raw->in6.sin6_addr,
-                       as_string_,
-                       INET6_ADDRSTRLEN);
+  socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa));
+  if (TEMP_FAILURE_RETRY(getnameinfo(sa,
+                                     salen,
+                                     as_string_,
+                                     INET6_ADDRSTRLEN,
+                                     NULL,
+                                     0,
+                                     NI_NUMERICHOST)) != 0) {
+    as_string_[0] = 0;
   }
-  if (result == NULL) as_string_[0] = 0;
-  memmove(reinterpret_cast<void *>(&addr_),
-          sockaddr,
-          GetAddrLength(raw));
+  memmove(reinterpret_cast<void *>(&addr_), sa, salen);
 }
 
 
@@ -158,20 +151,17 @@
     Log::PrintErr("Error getpeername: %s\n", error_message);
     return false;
   }
-  const void* src;
-  if (raw.ss.ss_family == AF_INET6) {
-    src = reinterpret_cast<const void*>(&raw.in6.sin6_addr);
-  } else {
-    src = reinterpret_cast<const void*>(&raw.in.sin_addr);
-  }
-  if (inet_ntop(raw.ss.ss_family,
-                src,
-                host,
-                INET_ADDRSTRLEN) == NULL) {
+  if (TEMP_FAILURE_RETRY(getnameinfo(&raw.addr,
+                                     size,
+                                     host,
+                                     INET6_ADDRSTRLEN,
+                                     NULL,
+                                     0,
+                                     NI_NUMERICHOST)) != 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
     strerror_r(errno, error_message, kBufferSize);
-    Log::PrintErr("Error inet_ntop: %s\n", error_message);
+    Log::PrintErr("Error getnameinfo: %s\n", error_message);
     return false;
   }
   *port = SocketAddress::GetAddrPort(&raw);
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 0042aed..4fffbf7 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -484,7 +484,9 @@
           continue;
         }
         if (i == ERROR_EVENT) {
-          reportError(nativeGetError(), "");
+          if (!isClosing) {
+            reportError(nativeGetError(), "");
+          }
         } else if (!isClosed) {
           // If the connection is closed right after it's accepted, there's a
           // chance the close-handler is not set.
@@ -711,6 +713,8 @@
 
   int get port => _socket.port;
 
+  InternetAddress get address => _socket.address;
+
   Future close() => _socket.close().then((_) => this);
 
   void _pause() {
@@ -921,6 +925,8 @@
 
   int get port => _socket.port;
 
+  InternetAddress get address => _socket.address;
+
   Future close() => _socket.close().then((_) => this);
 }
 
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 87a0b30..a5d55a9 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -198,11 +198,11 @@
   if (handle == INVALID_HANDLE_VALUE) {
     return -1;
   }
-  FileHandle* file_handle = new FileHandle(handle);
-  if (file_handle == NULL) return -1;
-  file_handle->MarkDoesNotSupportOverlappedIO();
-  file_handle->EnsureInitialized(EventHandler::delegate());
-  return reinterpret_cast<intptr_t>(file_handle);
+  StdHandle* std_handle = new StdHandle(handle);
+  if (std_handle == NULL) return -1;
+  std_handle->MarkDoesNotSupportOverlappedIO();
+  std_handle->EnsureInitialized(EventHandler::delegate());
+  return reinterpret_cast<intptr_t>(std_handle);
 }
 
 
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index 7c4f4c4..f89950a 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -15,20 +15,9 @@
     'version_in_cc_file': 'vm/version_in.cc',
     'version_cc_file': '<(gen_source_dir)/version.cc',
 
-    # Disable the OpenGLUI embedder by default on desktop OSes.  Note,
-    # to build this on the desktop, you need GLUT installed.
-    'enable_openglui%': 0,
     'libdart_deps': ['libdart_lib_withcore', 'libdart_lib', 'libdart_vm',
                      'libjscre', 'libdouble_conversion',],
   },
-  'conditions': [
-    ['OS=="android" or enable_openglui==1', {
-        'includes': [
-          'embedders/openglui/openglui_embedder.gypi',
-        ],
-      },
-    ],
-  ],
   'targets': [
     {
       'target_name': 'libdart',
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.cc b/runtime/embedders/openglui/android/android_graphics_handler.cc
deleted file mode 100644
index f2c0ea2..0000000
--- a/runtime/embedders/openglui/android/android_graphics_handler.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "embedders/openglui/android/android_graphics_handler.h"
-#include "embedders/openglui/common/log.h"
-
-AndroidGraphicsHandler::AndroidGraphicsHandler(android_app* application,
-                                               const char* resource_path)
-    : GraphicsHandler(resource_path),
-      application_(application),
-      display_(EGL_NO_DISPLAY),
-      surface_(EGL_NO_SURFACE),
-      context_(EGL_NO_CONTEXT) {
-}
-
-int32_t AndroidGraphicsHandler::Start() {
-  EGLint format, numConfigs;
-  EGLConfig config;
-  const EGLint attributes[] = {
-      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-      EGL_NONE
-  };
-  static const EGLint ctx_attribs[] = {
-    EGL_CONTEXT_CLIENT_VERSION, 2,
-    EGL_NONE
-  };
-
-  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  if (display_ != EGL_NO_DISPLAY) {
-    LOGI("eglInitialize");
-    if (eglInitialize(display_, NULL, NULL)) {
-      LOGI("eglChooseConfig");
-      if (eglChooseConfig(display_, attributes, &config, 1, &numConfigs) &&
-          numConfigs > 0) {
-        LOGI("eglGetConfigAttrib returned %d configs\n", numConfigs);
-        if (eglGetConfigAttrib(display_, config,
-                               EGL_NATIVE_VISUAL_ID, &format)) {
-          ANativeWindow_setBuffersGeometry(application_->window, 0, 0, format);
-          surface_ = eglCreateWindowSurface(display_, config,
-                              (EGLNativeWindowType)application_->window, NULL);
-          if (surface_ != EGL_NO_SURFACE) {
-            LOGI("eglCreateContext");
-            context_ = eglCreateContext(display_, config, EGL_NO_CONTEXT,
-                                        ctx_attribs);
-            if (context_ != EGL_NO_CONTEXT) {
-              if (eglMakeCurrent(display_, surface_, surface_, context_) &&
-                  eglQuerySurface(display_, surface_, EGL_WIDTH, &width_) &&
-                  width_ > 0 &&
-                  eglQuerySurface(display_, surface_, EGL_HEIGHT, &height_) &&
-                  height_ > 0) {
-                LOGI("Got dimensions %d x %d\n", width_, height_);
-                SetViewport(0, 0, width_, height_);
-                LOGI("GL version %s\n", glGetString(GL_VERSION));
-                LOGI("GLSL version: %s\n",
-                    glGetString(GL_SHADING_LANGUAGE_VERSION));
-                return GraphicsHandler::Start();
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-  LOGE("Error starting graphics");
-  Stop();
-  return -1;
-}
-
-void AndroidGraphicsHandler::Stop() {
-  LOGI("Stopping graphics");
-  GraphicsHandler::Stop();
-  if (display_ != EGL_NO_DISPLAY) {
-    eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    if (context_ != EGL_NO_CONTEXT) {
-      eglDestroyContext(display_, context_);
-      context_ = EGL_NO_CONTEXT;
-    }
-    if (surface_ != EGL_NO_SURFACE) {
-      eglDestroySurface(display_, surface_);
-      surface_ = EGL_NO_SURFACE;
-    }
-    eglTerminate(display_);
-    display_ = EGL_NO_DISPLAY;
-  }
-}
-
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.h b/runtime/embedders/openglui/android/android_graphics_handler.h
deleted file mode 100644
index c157d95..0000000
--- a/runtime/embedders/openglui/android/android_graphics_handler.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_
-#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_
-
-#include <android_native_app_glue.h>
-#include "embedders/openglui/common/graphics_handler.h"
-
-class AndroidGraphicsHandler : public GraphicsHandler {
-  public:
-    AndroidGraphicsHandler(android_app* application,
-                           const char* resource_path);
-
-    int32_t Start();
-    void Stop();
-
-  private:
-    android_app* application_;
-    EGLDisplay display_;
-    EGLSurface surface_;
-    EGLContext context_;
-};
-
-#endif  // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_
-
diff --git a/runtime/embedders/openglui/android/android_input_handler.h b/runtime/embedders/openglui/android/android_input_handler.h
deleted file mode 100644
index 420e459..0000000
--- a/runtime/embedders/openglui/android/android_input_handler.h
+++ /dev/null
@@ -1,36 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_
-#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_
-
-#include "embedders/openglui/common/graphics_handler.h"
-#include "embedders/openglui/common/input_handler.h"
-
-class AndroidInputHandler : public InputHandler {
-  public:
-    AndroidInputHandler(VMGlue* vm_glue,
-                        GraphicsHandler* graphics_handler)
-      : InputHandler(vm_glue),
-        graphics_handler_(graphics_handler) {
-    }
-
-  public:
-    int32_t Start() {
-      if (graphics_handler_->width() == 0 ||
-          graphics_handler_->height() == 0) {
-        return -1;
-      }
-      return 0;
-    }
-
-    void Stop() {
-    }
-
-  private:
-    GraphicsHandler* graphics_handler_;
-};
-
-#endif  // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_
-
diff --git a/runtime/embedders/openglui/android/android_log.h b/runtime/embedders/openglui/android/android_log.h
deleted file mode 100644
index ff82d0b..0000000
--- a/runtime/embedders/openglui/android/android_log.h
+++ /dev/null
@@ -1,17 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_
-#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_
-
-#include <android/log.h>
-
-#define LOGX(LOG_LEVEL, ...) do { \
-    __android_log_print(LOG_LEVEL, "DartExt", __VA_ARGS__); \
-  } while (0)
-#define LOGI(...) LOGX(ANDROID_LOG_INFO, __VA_ARGS__)
-#define LOGE(...) LOGX(ANDROID_LOG_ERROR, __VA_ARGS__)
-
-#endif  // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_
-
diff --git a/runtime/embedders/openglui/android/android_resource.h b/runtime/embedders/openglui/android/android_resource.h
deleted file mode 100644
index 85e0614..0000000
--- a/runtime/embedders/openglui/android/android_resource.h
+++ /dev/null
@@ -1,67 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_
-#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_
-
-#include <android_native_app_glue.h>
-
-#include "embedders/openglui/common/log.h"
-#include "embedders/openglui/common/resource.h"
-
-class AndroidResource : public Resource {
-  public:
-    AndroidResource(android_app* application, const char* path)
-        : Resource(path),
-          asset_manager_(application->activity->assetManager),
-          asset_(NULL) {
-    }
-
-    int32_t descriptor() {
-      if (Open() == 0) {
-        descriptor_ = AAsset_openFileDescriptor(asset_, &start_, &length_);
-        LOGI("%s has start %d, length %d, fd %d",
-             path_, static_cast<int>(start_), static_cast<int>(length_),
-             descriptor_);
-        return descriptor_;
-      }
-      return -1;
-    }
-
-    off_t length() {
-      if (length_ < 0) {
-        length_ = AAsset_getLength(asset_);
-      }
-      return length_;
-    }
-
-    int32_t Open() {
-      LOGI("Attempting to open asset %s", path_);
-      asset_ = AAssetManager_open(asset_manager_, path_, AASSET_MODE_UNKNOWN);
-      if (asset_ != NULL) {
-        return 0;
-      }
-      LOGE("Could not open asset %s", path_);
-      return -1;
-    }
-
-    void Close() {
-      if (asset_ != NULL) {
-        AAsset_close(asset_);
-        asset_ = NULL;
-      }
-    }
-
-    int32_t Read(void* buffer, size_t count) {
-      size_t actual = AAsset_read(asset_, buffer, count);
-      return (actual == count) ? 0 : -1;
-    }
-
-  private:
-    AAssetManager* asset_manager_;
-    AAsset* asset_;
-};
-
-#endif  // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_
-
diff --git a/runtime/embedders/openglui/android/android_sound_handler.cc b/runtime/embedders/openglui/android/android_sound_handler.cc
deleted file mode 100644
index de9e977..0000000
--- a/runtime/embedders/openglui/android/android_sound_handler.cc
+++ /dev/null
@@ -1,277 +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.
-
-#include "embedders/openglui/android/android_sound_handler.h"
-
-#include "embedders/openglui/android/android_resource.h"
-#include "embedders/openglui/common/log.h"
-
-AndroidSoundHandler::AndroidSoundHandler(android_app* application)
-    : SoundHandler(),
-      application_(application),
-      engine_(NULL),
-      engine_if_(NULL),
-      output_mix_(NULL),
-      background_player_(NULL),
-      background_player_if_(NULL),
-      background_player_seek_if_(NULL),
-      sample_player_(NULL),
-      sample_player_if_(NULL),
-      sample_player_queue_(NULL) {
-}
-
-int32_t AndroidSoundHandler::Start() {
-  LOGI("Starting SoundService");
-
-  const SLInterfaceID k_engine_mix_IIDs[] = { SL_IID_ENGINE };
-  const SLboolean k_engine_mix_reqs[] = { SL_BOOLEAN_TRUE };
-  const SLInterfaceID k_output_mix_IIDs[] = {};
-  const SLboolean k_output_mix_reqs[] = {};
-  int32_t res = slCreateEngine(&engine_, 0, NULL, 1,
-                               k_engine_mix_IIDs, k_engine_mix_reqs);
-  if (res == SL_RESULT_SUCCESS) {
-    res = (*engine_)->Realize(engine_, SL_BOOLEAN_FALSE);
-    if (res == SL_RESULT_SUCCESS) {
-      res = (*engine_)->GetInterface(engine_, SL_IID_ENGINE, &engine_if_);
-      if (res == SL_RESULT_SUCCESS) {
-        res = (*engine_if_)->CreateOutputMix(engine_if_, &output_mix_, 0,
-                                  k_output_mix_IIDs, k_output_mix_reqs);
-        if (res == SL_RESULT_SUCCESS) {
-          res = (*output_mix_)->Realize(output_mix_, SL_BOOLEAN_FALSE);
-          if (res == SL_RESULT_SUCCESS) {
-            if (StartSamplePlayer() == 0) {
-              return 0;
-            }
-          }
-        }
-      }
-    }
-  }
-  LOGI("Failed to start SoundService");
-  Stop();
-  return -1;
-}
-
-void AndroidSoundHandler::Stop() {
-  LOGI("Stopping SoundService");
-  if (sample_player_ != NULL) {
-    LOGI("Destroying sample player");
-    (*sample_player_)->Destroy(sample_player_);
-    sample_player_ = NULL;
-    sample_player_if_ = NULL;
-    sample_player_queue_ = NULL;
-  }
-  samples_.clear();
-  if (output_mix_ != NULL) {
-    LOGI("Destroying output mix");
-    (*output_mix_)->Destroy(output_mix_);
-    output_mix_ = NULL;
-  }
-  if (engine_ != NULL) {
-    LOGI("Destroying engine");
-    (*engine_)->Destroy(engine_);
-    engine_ = NULL;
-    engine_if_ = NULL;
-  }
-}
-
-int32_t AndroidSoundHandler::SetBackgroundPlayerState(int state) {
-  if (background_player_if_ != NULL) {
-    SLuint32 state;
-    (*background_player_)->GetState(background_player_, &state);
-    if (state == SL_OBJECT_STATE_REALIZED) {
-      (*background_player_if_)->SetPlayState(background_player_if_,
-                                             state);
-      return 0;
-    }
-  }
-  return -1;
-}
-
-int32_t AndroidSoundHandler::Pause() {
-  return SetBackgroundPlayerState(SL_PLAYSTATE_PAUSED);
-}
-
-
-int32_t AndroidSoundHandler::Resume() {
-  return SetBackgroundPlayerState(SL_PLAYSTATE_PLAYING);
-}
-
-int32_t AndroidSoundHandler::CreateAudioPlayer(SLEngineItf engine_if,
-                                        const SLInterfaceID extra_if,
-                                        SLDataSource data_source,
-                                        SLDataSink data_sink,
-                                        SLObjectItf& player_out,
-                                        SLPlayItf& player_if_out) {
-  const SLuint32 SoundPlayerIIDCount = 2;
-  const SLInterfaceID SoundPlayerIIDs[] = { SL_IID_PLAY, extra_if };
-  const SLboolean SoundPlayerReqs[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
-  int32_t res = (*engine_if)->CreateAudioPlayer(engine_if,
-                                                &player_out,
-                                                &data_source,
-                                                &data_sink,
-                                                SoundPlayerIIDCount,
-                                                SoundPlayerIIDs,
-                                                SoundPlayerReqs);
-
-  if (res == SL_RESULT_SUCCESS) {
-    res = (*player_out)->Realize(player_out, SL_BOOLEAN_FALSE);
-    if (res == SL_RESULT_SUCCESS) {
-      res = (*player_out)->GetInterface(sample_player_,
-                                            SL_IID_PLAY,
-                                            &player_if_out);
-      if (res == SL_RESULT_SUCCESS) {
-        return 0;
-      }
-    }
-  }
-  return -1;
-}
-
-int32_t AndroidSoundHandler::PlayBackground(const char* path) {
-  LOGI("Creating audio player");
-
-  Resource resource(path);
-  int fd = resource.descriptor();
-  if (fd < 0) {
-    LOGI("Could not open file %s", path);
-    return -1;
-  }
-
-  SLDataLocator_AndroidFD data_locator_in = {
-      SL_DATALOCATOR_ANDROIDFD,
-      fd,
-      resource.start(),
-      resource.length()
-  };
-  SLDataFormat_MIME data_format = {
-      SL_DATAFORMAT_MIME,
-      NULL,
-      SL_CONTAINERTYPE_UNSPECIFIED
-  };
-  SLDataSource data_source = { &data_locator_in, &data_format };
-
-  resource.Close();
-
-  SLDataLocator_OutputMix data_locator_out =
-      { SL_DATALOCATOR_OUTPUTMIX, output_mix_ };
-  SLDataSink data_sink = { &data_locator_out, NULL };
-
-  int32_t res = CreateAudioPlayer(engine_if_,
-                                  SL_IID_SEEK,
-                                  data_source,
-                                  data_sink,
-                                  background_player_,
-                                  background_player_if_);
-
-  if (res != SL_RESULT_SUCCESS) {
-    LOGE("Couldn't create audio player");
-    return -1;
-  }
-
-  if ((*background_player_)->
-          GetInterface(background_player_, SL_IID_SEEK,
-                       &background_player_seek_if_) != SL_RESULT_SUCCESS) {
-    LOGE("Couldn't get seek interface");
-    return -1;
-  }
-  LOGI("Got seek interface");
-  if ((*background_player_seek_if_)->
-          SetLoop(background_player_seek_if_, SL_BOOLEAN_TRUE, 0,
-                  SL_TIME_UNKNOWN) != SL_RESULT_SUCCESS) {
-    LOGE("Couldn't set loop");
-    return -1;
-  }
-  LOGI("Set loop");
-  if ((*background_player_if_)->
-          SetPlayState(background_player_if_, SL_PLAYSTATE_PLAYING) !=
-          SL_RESULT_SUCCESS) {
-    LOGE("Couldn't start playing");
-    return -1;
-  }
-  LOGI("Started playing");
-  return 0;
-}
-
-void AndroidSoundHandler::StopBackground() {
-  if (Pause() == 0) {
-    (*background_player_)->Destroy(background_player_);
-    background_player_ = NULL;
-    background_player_if_ = NULL;
-    background_player_seek_if_ = NULL;
-  }
-}
-
-int32_t AndroidSoundHandler::StartSamplePlayer() {
-  SLDataLocator_AndroidSimpleBufferQueue data_locator_in = {
-    SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
-    1
-  };
-
-  SLDataFormat_PCM data_format= {
-    SL_DATAFORMAT_PCM,
-    1,
-    SL_SAMPLINGRATE_44_1,
-    SL_PCMSAMPLEFORMAT_FIXED_16,
-    SL_PCMSAMPLEFORMAT_FIXED_16,
-    SL_SPEAKER_FRONT_CENTER,
-    SL_BYTEORDER_LITTLEENDIAN
-  };
-
-  SLDataSource data_source = { &data_locator_in, &data_format };
-
-  SLDataLocator_OutputMix data_locator_out =
-      { SL_DATALOCATOR_OUTPUTMIX, output_mix_ };
-  SLDataSink data_sink = { &data_locator_out, NULL };
-
-  int32_t res = CreateAudioPlayer(engine_if_, SL_IID_BUFFERQUEUE,
-                                  data_source,
-                                  data_sink,
-                                  sample_player_, sample_player_if_);
-
-  if (res == SL_RESULT_SUCCESS) {
-    res = (*sample_player_)->GetInterface(sample_player_,
-                                          SL_IID_BUFFERQUEUE,
-                                          &sample_player_queue_);
-    if (res == SL_RESULT_SUCCESS) {
-      res = (*sample_player_if_)->SetPlayState(sample_player_if_,
-                                               SL_PLAYSTATE_PLAYING);
-      if (res == SL_RESULT_SUCCESS) {
-        return 0;
-      }
-    }
-  }
-  LOGE("Error while starting sample player");
-  return -1;
-}
-
-int32_t AndroidSoundHandler::PlaySample(const char* path) {
-  SLuint32 state;
-  (*sample_player_)->GetState(sample_player_, &state);
-  if (state != SL_OBJECT_STATE_REALIZED) {
-    LOGE("Sample player has not been realized");
-  } else {
-    Sample* sample = GetSample(path);
-    if (sample != NULL) {
-      int16_t* buffer = reinterpret_cast<int16_t*>(sample->buffer());
-      off_t len = sample->length();
-
-      // Remove any current sample.
-      int32_t res = (*sample_player_queue_)->Clear(sample_player_queue_);
-      if (res == SL_RESULT_SUCCESS) {
-        res = (*sample_player_queue_)->Enqueue(sample_player_queue_,
-                                               buffer, len);
-        if (res == SL_RESULT_SUCCESS) {
-          LOGE("Enqueued sample %s of length %d", path,
-            static_cast<int>(len));
-          return 0;
-        }
-        LOGE("Enqueueing sample failed");
-      }
-    }
-  }
-  return -1;
-}
-
-
diff --git a/runtime/embedders/openglui/android/android_sound_handler.h b/runtime/embedders/openglui/android/android_sound_handler.h
deleted file mode 100644
index e699a69..0000000
--- a/runtime/embedders/openglui/android/android_sound_handler.h
+++ /dev/null
@@ -1,55 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_
-#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_
-
-#include <android_native_app_glue.h>
-#include <SLES/OpenSLES.h>
-#include <SLES/OpenSLES_Android.h>
-#include <SLES/OpenSLES_AndroidConfiguration.h>
-#include <vector>
-
-#include "embedders/openglui/common/sample.h"
-#include "embedders/openglui/common/sound_handler.h"
-#include "embedders/openglui/common/types.h"
-
-class AndroidSoundHandler : public SoundHandler {
-  public:
-    explicit AndroidSoundHandler(android_app* application);
-    int32_t Start();
-    void Stop();
-    int32_t Pause();
-    int32_t Resume();
-
-    int32_t PlayBackground(const char* path);
-    void StopBackground();
-
-    int32_t PlaySample(const char* path);
-
-  private:
-    int32_t CreateAudioPlayer(SLEngineItf engine_if,
-                              const SLInterfaceID extra_if,
-                              SLDataSource data_source,
-                              SLDataSink data_sink,
-                              SLObjectItf& player_out,
-                              SLPlayItf& player_if_out);
-
-    int32_t SetBackgroundPlayerState(int state);
-    int32_t StartSamplePlayer();
-
-    android_app* application_;
-    SLObjectItf engine_;
-    SLEngineItf engine_if_;
-    SLObjectItf output_mix_;
-    SLObjectItf background_player_;
-    SLPlayItf background_player_if_;
-    SLSeekItf background_player_seek_if_;
-    SLObjectItf sample_player_;
-    SLPlayItf sample_player_if_;
-    SLBufferQueueItf sample_player_queue_;
-};
-
-#endif  // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_
-
diff --git a/runtime/embedders/openglui/android/eventloop.cc b/runtime/embedders/openglui/android/eventloop.cc
deleted file mode 100644
index ed1645e..0000000
--- a/runtime/embedders/openglui/android/eventloop.cc
+++ /dev/null
@@ -1,464 +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.
-
-#include "embedders/openglui/android/eventloop.h"
-
-#include <time.h>
-#include "embedders/openglui/common/log.h"
-
-/*
- * The Android lifecycle events are:
- *
- * OnCreate: In NDK this is the call to android_main
- *
- * OnStart: technically, called to initiate the “visible” lifespan of the
- *     app; at any time between OnStart and OnStop, the app may be visible.
- *     We can either be OnResume’d or OnStop’ped from this state. Note that
- *     there is also an event for OnRestart, which is called before OnStart
- *     if the application is transitioning from OnStop to OnStart instead of
- *     being started from scratch.
- *
- * OnResume: technically, the start of the “foreground” lifespan of the app, 
- *     but this does not mean that the app is fully visible and should be 
- *     rendering – more on that later
- *
- * OnPause: the app is losing its foregrounded state; this is normally an 
- *     indication that something is fully covering the app. On versions of 
- *     Android before Honeycomb, once we returned from this callback, we 
- *     could be killed at any time with no further app code called. We can
- *     either be OnResume’d or OnStop’ped from this state. OnPause halts the 
- *     visible UI thread and so should be handled as quickly as possible.
- *
- * OnStop: the end of the current visible lifespan of the app – we may
- *     transition to On(Re)Start to become visible again, or to OnDestroy if
- *      we are shutting down entirely. Once we return from this callback, we
- *      can be killed at any time with no further app code called on any
- *      version of Android.
- *
- * OnDestroy: this can only be followed by the application being killed or
- *     restarted with OnCreate.
- *
- * The above events occur in fixed orders. The events below can occur at 
- * various times:
- *
- * OnGainedFocus: happens between OnResume and OnPause.
- * OnLostFocus:  may occur at arbitrary times, and may in fact not happen
- *     at all if the app is being destroyed. So OnPause and OnGainedFocus/
- *     OnLostFocus must be used together to determine the visible and
- *     interactable state of the app.
- *
- * OnCreateWindow: usually happens in the resumed state
- * OnDestroyWindow: can happen after OnPause or OnDestroy, so apps may
- *     need to handle shutting down EGL before their surfaces are
- *     destroyed.
- * OnConfigurationChanged: typically means the size has changed
- *
- * An application's EGL surface may only exist between the OnCreateWindow
- * and OnDestroyWindow callbacks.
- *
- * An application is "killable" after OnStop or OnDestroy (in earlier 
- * Android versions, after OnPause too). That means any critical state
- * or resources must be handled by any of these callbacks.
- *
- * These callbacks run on the main thread. If they block any event
- * processing for more than 5 seconds this will result in an ANR
- * (Application Not Responding message).
- *
- * On application launch, this sequence will occur:
- *
- * - OnCreate
- * - OnStart
- * - OnResume
- * - OnCreateWindow
- * - OnConfigurationChanged
- * - OnGainedFocus
- *
- * If the back button is pressed, and the app does not handle it,
- * Android will pop the app of the UI stack and destroy the application's
- * activity:
- *
- * - OnPause
- * - OnLostFocus
- * - OnDestroyWindow
- * - OnStop
- * - OnDestroy
- *
- * If the home button is pressed, the app is sent down in the UI stack.
- * The app's Activity still exists but may be killed at any time, and
- * it loses its rendering surface:
- *
- * - OnPause
- * - OnLostFocus
- * - OnDestroyWindow
- * - OnStop
- *
- * If the app is then restarted (without having been killed in between):
- *
- * - OnRestart
- * - OnStart
- * - OnResume
- * - OnCreateWindow
- * - OnConfigurationChanged
- * - OnGainedFocus
- *
- * If a status icon pop up is opened, the app is still visible and can render
- * but is not focused and cannot receive input:
- *
- * - OnLostFocus
- *
- * When the popup is dismissed, the app regains focus:
- *
- * - OnGainedFocus
- *
- * When the device is suspended (power button or screen saver), the application
- * will typically be paused and lose focus:
- *
- * - OnPause
- * - OnLostFocus (sometimes this will only come when the device is resumed
- *       to the lock screen)
- *
- * The application should have stopped all rendering and sound and any
- * non-critical background processing.
- *
- * When the device is resumed but not yet unlocked, the app will be resumed:
- * 
- * - OnResume
- *
- * The application should not perform sound or graphics yet. If the lock 
- * screen times out, the app will be paused again. If the screen is
- * unlocked, the app will regain focus.
- *
- * Turning all of this into a general framework, we can use the following:
- *
- * 1. In OnCreate/android_main, set up the main classes and possibly
- *    load some lightweight resources.
- * 2. In OnCreateWindow, create the EGLSurface, bind the context, load 
- *    OpenGL resources. No rendering.
- * 3. When we are between OnResume and OnPause, and between OnCreateWindow
- *    and OnDestroyWindow, and between OnGainedFocus and OnLostFocus,
- *    we can render and process input.
- * 4. In OnLostFocus, stop sounds from playing, and stop rendering.
- * 5. In OnPause, stop all rendering
- * 6. In OnResume, prepare to start rendering again, but don't render.
- * 7. In OnGainedFocus after OnResume, start rendering and sound again.
- * 8. In OnStop, free all graphic resources, either through GLES calls
- *    if the EGLContext is still bound, or via eglDestroyContext if the
- *    context has been unbound because the rendering surface was destroyed.
- * 9. In OnDestroy, release all other resources.
- */
-EventLoop::EventLoop(android_app* application)
-    : enabled_(false),
-      quit_(false),
-      isResumed_(false),
-      hasSurface_(false),
-      hasFocus_(false),
-      application_(application),
-      lifecycle_handler_(NULL),
-      input_handler_(NULL),
-      sensor_manager_(NULL),
-      sensor_event_queue_(NULL),
-      sensor_poll_source_() {
-  application_->onAppCmd = ActivityCallback;
-  application_->onInputEvent = InputCallback;
-  application_->userData = this;
-}
-
-static int64_t getTimeInMillis() {
-  struct timespec res;
-  clock_gettime(CLOCK_REALTIME, &res);
-  return 1000 * res.tv_sec + res.tv_nsec / 1000000;
-}
-
-void EventLoop::Run(LifeCycleHandler* lifecycle_handler,
-                    InputHandler* input_handler) {
-  int32_t result;
-  int32_t events;
-  android_poll_source* source;
-
-  lifecycle_handler_ = lifecycle_handler;
-  input_handler_ = input_handler;
-  int64_t last_frame_time = getTimeInMillis();
-  if (lifecycle_handler_->OnStart() == 0) {
-    LOGI("Starting event loop");
-    while (!quit_) {
-      // If not enabled, block indefinitely on events. If enabled, block
-      // briefly so we can do useful work in onStep, but only long
-      // enough that we can still do work at 60fps if possible.
-      int64_t next_frame_time = last_frame_time + (1000/60);
-      int64_t next_frame_delay = next_frame_time - getTimeInMillis();
-      if (next_frame_delay < 0) next_frame_delay = 0;
-      while ((result = ALooper_pollAll(enabled_ ? next_frame_delay : -1, NULL,
-          &events, reinterpret_cast<void**>(&source))) >= 0) {
-        if (source != NULL) {
-          source->process(application_, source);
-        }
-        if (application_->destroyRequested) {
-          return;
-        }
-      }
-      if (enabled_ && !quit_) {
-        int64_t now = getTimeInMillis();
-        if (now >= next_frame_time) {
-          LOGI("step");
-          last_frame_time = now;
-          if (lifecycle_handler_->OnStep() != 0) {
-            quit_ = true;
-          }
-        }
-      }
-    }
-  }
-  ANativeActivity_finish(application_->activity);
-}
-
-void EventLoop::EnableSensorEvents() {
-  sensor_poll_source_.id = LOOPER_ID_USER;
-  sensor_poll_source_.app = application_;
-  sensor_poll_source_.process = SensorCallback;
-  sensor_manager_ = ASensorManager_getInstance();
-  if (sensor_manager_ != NULL) {
-    sensor_event_queue_ = ASensorManager_createEventQueue(
-        sensor_manager_, application_->looper,
-        LOOPER_ID_USER, NULL, &sensor_poll_source_);
-
-    sensor_ = ASensorManager_getDefaultSensor(sensor_manager_,
-        ASENSOR_TYPE_ACCELEROMETER);
-    if (sensor_ != NULL) {
-      int32_t min_delay = ASensor_getMinDelay(sensor_);
-      if (ASensorEventQueue_enableSensor(sensor_event_queue_, sensor_) < 0 ||
-          ASensorEventQueue_setEventRate(sensor_event_queue_, sensor_,
-              min_delay) < 0) {
-        LOGE("Error while activating sensor.");
-        DisableSensorEvents();
-        return;
-      }
-      LOGI("Activating sensor:");
-      LOGI("Name       : %s", ASensor_getName(sensor_));
-      LOGI("Vendor     : %s", ASensor_getVendor(sensor_));
-      LOGI("Resolution : %f", ASensor_getResolution(sensor_));
-      LOGI("Min Delay  : %d", min_delay);
-    } else {
-      LOGI("No sensor");
-    }
-  }
-}
-
-void EventLoop::DisableSensorEvents() {
-  if (sensor_ != NULL) {
-    if (ASensorEventQueue_disableSensor(sensor_event_queue_, sensor_) < 0) {
-      LOGE("Error while deactivating sensor.");
-    }
-    sensor_ = NULL;
-  }
-  if (sensor_event_queue_ != NULL) {
-    ASensorManager_destroyEventQueue(sensor_manager_,
-                    sensor_event_queue_);
-    sensor_event_queue_ = NULL;
-  }
-  sensor_manager_ = NULL;
-}
-
-void EventLoop::ProcessActivityEvent(int32_t command) {
-  switch (command) {
-    case APP_CMD_INIT_WINDOW:
-      if (lifecycle_handler_->Activate() != 0) {
-        quit_ = true;
-      } else {
-        hasSurface_ = true;
-      }
-      break;
-    case APP_CMD_CONFIG_CHANGED:
-      lifecycle_handler_->OnConfigurationChanged();
-      break;
-    case APP_CMD_DESTROY:
-      hasFocus_ = false;
-      lifecycle_handler_->FreeAllResources();
-      break;
-    case APP_CMD_GAINED_FOCUS:
-      hasFocus_ = true;
-      if (hasSurface_ && isResumed_ && hasFocus_) {
-        enabled_ = (lifecycle_handler_->Resume() == 0);
-        if (enabled_) {
-          EnableSensorEvents();
-        }
-      }
-      break;
-    case APP_CMD_LOST_FOCUS:
-      hasFocus_ = false;
-      enabled_ = false;
-      DisableSensorEvents();
-      lifecycle_handler_->Pause();
-      break;
-    case APP_CMD_LOW_MEMORY:
-      lifecycle_handler_->OnLowMemory();
-      break;
-    case APP_CMD_PAUSE:
-      isResumed_ = false;
-      enabled_ = false;
-      DisableSensorEvents();
-      lifecycle_handler_->Pause();
-      break;
-    case APP_CMD_RESUME:
-      isResumed_ = true;
-      break;
-    case APP_CMD_SAVE_STATE:
-      lifecycle_handler_->OnSaveState(&application_->savedState,
-                                    &application_->savedStateSize);
-      break;
-    case APP_CMD_START:
-      break;
-    case APP_CMD_STOP:
-      hasFocus_ = false;
-      lifecycle_handler_->Deactivate();
-      break;
-    case APP_CMD_TERM_WINDOW:
-      hasFocus_ = false;
-      hasSurface_ = false;
-      enabled_ = false;
-      DisableSensorEvents();
-      lifecycle_handler_->Pause();
-      break;
-    default:
-      break;
-  }
-}
-
-void EventLoop::ProcessSensorEvent() {
-  ASensorEvent event;
-  while (ASensorEventQueue_getEvents(sensor_event_queue_, &event, 1) > 0) {
-    switch (event.type) {
-      case ASENSOR_TYPE_ACCELEROMETER:
-        input_handler_->OnAccelerometerEvent(event.vector.x,
-            event.vector.y, event.vector.z);
-        break;
-    }
-  }
-}
-
-bool EventLoop::OnTouchEvent(AInputEvent* event) {
-  int32_t type = AMotionEvent_getAction(event);
-  MotionEvent motion_event;
-  switch (type) {
-    case AMOTION_EVENT_ACTION_DOWN:
-      motion_event = kMotionDown;
-      break;
-    case AMOTION_EVENT_ACTION_UP:
-      motion_event = kMotionUp;
-      break;
-    case AMOTION_EVENT_ACTION_MOVE:
-      motion_event = kMotionMove;
-      break;
-    case AMOTION_EVENT_ACTION_CANCEL:
-      motion_event = kMotionCancel;
-      break;
-    case AMOTION_EVENT_ACTION_OUTSIDE:
-      motion_event = kMotionOutside;
-      break;
-    case AMOTION_EVENT_ACTION_POINTER_DOWN:
-      motion_event = kMotionPointerDown;
-      break;
-    case AMOTION_EVENT_ACTION_POINTER_UP:
-      motion_event = kMotionPointerUp;
-      break;
-    default:
-      return false;
-  }
-  // For now we just get the last coords.
-  float move_x = AMotionEvent_getX(event, 0);
-  float move_y = AMotionEvent_getY(event, 0);
-  int64_t when = AMotionEvent_getEventTime(event);
-  LOGI("Got motion event %d at %f, %f", type, move_x, move_y);
-
-  if (input_handler_->OnMotionEvent(motion_event, when, move_x, move_y) != 0) {
-    return false;
-  }
-  return true;
-}
-
-bool EventLoop::OnKeyEvent(AInputEvent* event) {
-  int32_t type = AKeyEvent_getAction(event);
-  KeyEvent key_event;
-  switch (type) {
-    case AKEY_EVENT_ACTION_DOWN:
-      key_event = kKeyDown;
-      break;
-    case AKEY_EVENT_ACTION_UP:
-      key_event = kKeyUp;
-      break;
-    case AKEY_EVENT_ACTION_MULTIPLE:
-      key_event = kKeyMultiple;
-      break;
-    default:
-      return false;
-  }
-  /* Get the key code of the key event.
-   * This is the physical key that was pressed, not the Unicode character. */
-  int32_t key_code = AKeyEvent_getKeyCode(event);
-  /* Get the meta key state. */
-  int32_t meta_state = AKeyEvent_getMetaState(event);
-  /* Get the repeat count of the event.
-   * For both key up an key down events, this is the number of times the key
-   * has repeated with the first down starting at 0 and counting up from
-   * there.  For multiple key events, this is the number of down/up pairs
-   * that have occurred. */
-  int32_t repeat = AKeyEvent_getRepeatCount(event);
-
-  /* Get the time of the most recent key down event, in the	
-   * java.lang.System.nanoTime() time base.  If this is a down event,	
-   * this will be the same as eventTime.	
-   * Note that when chording keys, this value is the down time of the most	
-   * recently pressed key, which may not be the same physical key of this	
-   * event. */	
-  // TODO(gram): Use or remove this.
-  // int64_t key_down_time = AKeyEvent_getDownTime(event);
-
-  /* Get the time this event occurred, in the
-   * java.lang.System.nanoTime() time base. */
-  int64_t when = AKeyEvent_getEventTime(event);
-  bool isAltKeyDown = (meta_state & AMETA_ALT_ON) != 0;
-  bool isShiftKeyDown = (meta_state & AMETA_SHIFT_ON) != 0;
-  bool isCtrlKeyDown = key_code < 32;
-
-  LOGI("Got key event %d %d", type, key_code);
-
-  if (input_handler_->OnKeyEvent(key_event, when, key_code,
-                                 isAltKeyDown, isCtrlKeyDown, isShiftKeyDown,
-                                 repeat) != 0) {
-    return false;
-  }
-  return true;
-}
-
-int32_t EventLoop::ProcessInputEvent(AInputEvent* event) {
-  int32_t event_type = AInputEvent_getType(event);
-  LOGI("Got input event type %d", event_type);
-  switch (event_type) {
-    case AINPUT_EVENT_TYPE_MOTION:
-      if (AInputEvent_getSource(event) == AINPUT_SOURCE_TOUCHSCREEN) {
-          return OnTouchEvent(event);
-      }
-      break;
-    case AINPUT_EVENT_TYPE_KEY:
-      return OnKeyEvent(event);
-  }
-  return 0;
-}
-
-void EventLoop::ActivityCallback(android_app* application, int32_t command) {
-  EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData);
-  event_loop->ProcessActivityEvent(command);
-}
-
-int32_t EventLoop::InputCallback(android_app* application,
-                                 AInputEvent* event) {
-  EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData);
-  return event_loop->ProcessInputEvent(event);
-}
-
-void EventLoop::SensorCallback(android_app* application,
-    android_poll_source* source) {
-  EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData);
-  event_loop->ProcessSensorEvent();
-}
-
diff --git a/runtime/embedders/openglui/android/eventloop.h b/runtime/embedders/openglui/android/eventloop.h
deleted file mode 100644
index 031bf69..0000000
--- a/runtime/embedders/openglui/android/eventloop.h
+++ /dev/null
@@ -1,51 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_
-#define EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_
-
-#include <android_native_app_glue.h>
-#include <android/sensor.h>
-#include "embedders/openglui/common/events.h"
-#include "embedders/openglui/common/input_handler.h"
-#include "embedders/openglui/common/lifecycle_handler.h"
-
-class EventLoop {
-  public:
-    explicit EventLoop(android_app* application);
-    void Run(LifeCycleHandler* activity_handler,
-             InputHandler* input_handler);
-
-  protected:
-    void EnableSensorEvents();
-    void DisableSensorEvents();
-
-    void ProcessActivityEvent(int32_t command);
-    int32_t ProcessInputEvent(AInputEvent* event);
-    void ProcessSensorEvent();
-
-    bool OnTouchEvent(AInputEvent* event);
-    bool OnKeyEvent(AInputEvent* event);
-
-    static void ActivityCallback(android_app* application, int32_t command);
-    static int32_t InputCallback(android_app* application, AInputEvent* event);
-    static void SensorCallback(android_app* application,
-        android_poll_source* source);
-
-  private:
-    friend class Sensor;
-
-    bool enabled_, quit_;
-    bool isResumed_, hasSurface_, hasFocus_;
-    android_app* application_;
-    LifeCycleHandler* lifecycle_handler_;
-    InputHandler* input_handler_;
-    const ASensor* sensor_;
-    ASensorManager* sensor_manager_;
-    ASensorEventQueue* sensor_event_queue_;
-    android_poll_source sensor_poll_source_;
-};
-
-#endif  // EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_
-
diff --git a/runtime/embedders/openglui/android/main.cc b/runtime/embedders/openglui/android/main.cc
deleted file mode 100644
index c0c386b..0000000
--- a/runtime/embedders/openglui/android/main.cc
+++ /dev/null
@@ -1,39 +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.
-
-#include "embedders/openglui/android/android_graphics_handler.h"
-#include "embedders/openglui/android/android_input_handler.h"
-#include "embedders/openglui/android/android_resource.h"
-#include "embedders/openglui/android/android_sound_handler.h"
-#include "embedders/openglui/android/eventloop.h"
-#include "embedders/openglui/common/context.h"
-#include "embedders/openglui/common/dart_host.h"
-#include "embedders/openglui/common/vm_glue.h"
-
-android_app* application_ = NULL;
-
-Resource* MakePlatformResource(const char *path) {
-  return new AndroidResource(application_, path);
-}
-
-void android_main(android_app* application) {
-  application_ = application;
-  app_dummy();  // Link in native_app_glue.
-  const char* resource_path = "/data/data/com.google.dartndk/app_dart";
-  EventLoop eventLoop(application);
-  AndroidGraphicsHandler graphics_handler(application, resource_path);
-  VMGlue vm_glue(&graphics_handler, resource_path);
-  AndroidInputHandler input_handler(&vm_glue, &graphics_handler);
-  AndroidSoundHandler sound_handler(application);
-  Timer timer;
-  Context app_context;
-  app_context.graphics_handler = &graphics_handler;
-  app_context.input_handler = &input_handler;
-  app_context.sound_handler = &sound_handler;
-  app_context.timer = &timer;
-  app_context.vm_glue = &vm_glue;
-  DartHost host(&app_context);
-  eventLoop.Run(&host, &input_handler);
-}
-
diff --git a/runtime/embedders/openglui/android/support_android.cc b/runtime/embedders/openglui/android/support_android.cc
deleted file mode 100644
index 6755f15..0000000
--- a/runtime/embedders/openglui/android/support_android.cc
+++ /dev/null
@@ -1,15 +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.
-
-// Provide atexit, not part of Android libc or linker.
-
-extern "C" int atexit(void (*function)(void)) {
-  // Return error code.
-  return 1;
-}
-
-// Provide __dso_handle, not part of Android libc or linker.
-
-__attribute__((weak)) void *__dso_handle;
-
diff --git a/runtime/embedders/openglui/build_skia.sh b/runtime/embedders/openglui/build_skia.sh
deleted file mode 100755
index 42710a8..0000000
--- a/runtime/embedders/openglui/build_skia.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/bin/bash
-
-function usage {
-  echo "usage: $0 [ --help ] [ --android ] [ --arm | --x86] [ --debug ] [--clean] [<Dart directory>]"
-  echo
-  echo "Sync up Skia and build"
-  echo
-  echo " --android: Build for Android"
-  echo " --x86 : Build for Intel"
-  echo " --arm : Cross-compile for ARM (implies --android)"
-  echo " --debug : Build a debug version"
-  echo
-}
-
-DO_ANDROID=0
-TARGET_ARCH=x86
-CLEAN=0
-BUILD=Release
-DART_DIR=../../..
-
-while [ ! -z "$1" ] ; do
-  case $1 in
-    "-h"|"-?"|"-help"|"--help")
-      usage
-      exit 1
-    ;;
-    "--android")
-      DO_ANDROID=1
-    ;;
-    "--arm")
-      TARGET_ARCH=arm
-      DO_ANDROID=1
-    ;;
-    "--x86")
-      TARGET_ARCH=x86
-    ;;
-    "--clean")
-      CLEAN=1
-    ;;
-    "--debug")
-      BUILD=Debug
-    ;;
-    "--release")
-      BUILD=Release
-    ;;
-    *)
-      if [ ! -d "$1" ]
-      then
-        echo "Unrecognized argument: $1"
-        usage
-        exit 1
-      fi
-      DART_DIR="$1"
-    ;;
-  esac
-  shift
-done
-
-mkdir -p "${DART_DIR}/third_party/skia"
-pushd "${DART_DIR}/third_party/skia"
-
-if [ ${DO_ANDROID} != 0 ] ; then
-  echo "Building for Android ${TARGET_ARCH}"
-  curl http://skia.googlecode.com/svn/trunk/platform_tools/android/gclient.config -o .gclient
-  gclient sync
-
-  export ANDROID_SDK_ROOT=`readlink -f ../android_tools/sdk`
-  export GSUTIL_LOCATION=`readlink -f ../gsutil`
-
-  cd trunk
-
-  echo "Using SDK ${ANDROID_SDK_ROOT}"
-  if [ ${CLEAN} != 0 ] ; then
-    ./platform_tools/android/bin/android_make -d $TARGET_ARCH -j clean
-  else
-    echo env -i BUILDTYPE=$BUILD ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" PATH="${PATH}:${GSUTIL_LOCATION}" ../android/bin/android_make BUILDTYPE=$BUILD -d $TARGET_ARCH -j --debug=j
-    env -i BUILDTYPE=$BUILD ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" PATH="${PATH}:${GSUTIL_LOCATION}" ./platform_tools/android/bin/android_make BUILDTYPE=$BUILD -d $TARGET_ARCH -j --debug=j
-  fi
-
-else
-
-  echo "Building for desktop in `pwd`"
-  # Desktop build. Requires svn client and Python.
-
-  # Note that on Linux these packages should be installed first:
-  #
-  # libfreetype6
-  # libfreetype6-dev
-  # libpng12-0, libpng12-dev
-  # libglu1-mesa-dev
-  # mesa-common-dev
-  # freeglut3-dev
-
-  SKIA_INSTALLDIR=`pwd`
-  svn checkout http://skia.googlecode.com/svn/trunk
-  cd trunk
-  if [ ${CLEAN} != 0 ] ; then
-    echo 'Cleaning'
-    make clean
-  else
-    # Dart sets BUILDTYPE to DebugX64 which breaks Skia build.
-    make BUILDTYPE=$BUILD
-  fi
-  cd ..
-
-fi
-
-popd
-# TODO(gram) We should really propogate the make exit code here.
-exit 0
-
-
diff --git a/runtime/embedders/openglui/common/canvas_context.cc b/runtime/embedders/openglui/common/canvas_context.cc
deleted file mode 100644
index 24c0f7d..0000000
--- a/runtime/embedders/openglui/common/canvas_context.cc
+++ /dev/null
@@ -1,107 +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.
-
-#include "embedders/openglui/common/canvas_context.h"
-
-#include <ctype.h>
-#include <string.h>
-#include "core/SkStream.h"
-#include "embedders/openglui/common/image_cache.h"
-#include "embedders/openglui/common/support.h"
-
-// TODO(gram): this should be dynamic.
-#define MAX_CONTEXTS 256
-CanvasContext* contexts[MAX_CONTEXTS] = { 0 };
-
-CanvasContext* Context2D(int handle) {
-  if (handle < 0 || handle >= MAX_CONTEXTS) {
-    LOGE("Request for out-of-range handle %d", handle);
-    return NULL;
-  }
-  if (contexts[handle] == NULL) {
-    LOGE("Warning: request for context with handle %d returns NULL", handle);
-  }
-  return contexts[handle];
-}
-
-void FreeContexts() {
-  extern CanvasContext* display_context;
-  for (int i = 0; i < MAX_CONTEXTS; i++) {
-    delete contexts[i];
-    contexts[i] = NULL;
-  }
-  display_context = NULL;
-}
-
-
-CanvasContext::CanvasContext(int handle, int16_t widthp, int16_t heightp)
-  : canvas_(NULL),
-    width_(widthp),
-    height_(heightp),
-    imageSmoothingEnabled_(true),
-    state_(NULL) {
-  if (handle >= MAX_CONTEXTS) {
-    LOGE("Max contexts exceeded");
-    exit(-1);
-  }
-  if (handle == 0) {
-    canvas_ = graphics->CreateDisplayCanvas();
-  } else {
-    canvas_ = graphics->CreateBitmapCanvas(widthp, heightp);
-  }
-  state_ = new CanvasState(canvas_);
-  contexts[handle] = this;
-  LOGI("Created context with handle %d", handle);
-}
-
-CanvasContext::~CanvasContext() {
-  delete state_;
-  delete canvas_;
-}
-
-void CanvasContext::Save() {
-  state_ = state_->Save();
-}
-
-void CanvasContext::Restore() {
-  CanvasState* popped_state = state_;
-  state_ = state_->Restore();
-  if (state_ == NULL) {
-    LOGE("Popping last state!");
-    state_ = popped_state;
-  }
-  if (state_ != popped_state) {
-    // Only delete if the pop was successful.
-    delete popped_state;
-  }
-}
-
-void CanvasContext::DrawImage(const char* src_url,
-                              int sx, int sy,
-                              bool has_src_dimensions, int sw, int sh,
-                              int dx, int dy,
-                              bool has_dst_dimensions, int dw, int dh) {
-  const SkBitmap* bm = ImageCache::GetImage(src_url);
-  if (bm == NULL) return;
-  if (!has_src_dimensions) {
-    sw = bm->width();
-    sh = bm->height();
-  }
-  if (!has_dst_dimensions) {
-    dw = bm->width();
-    dh = bm->height();
-  }
-  state_->DrawImage(*bm, sx, sy, sw, sh, dx, dy, dw, dh);
-  isDirty_ = true;
-}
-
-void CanvasContext::ClearRect(float left, float top,
-                              float width, float height) {
-  SkPaint paint;
-  paint.setStyle(SkPaint::kFill_Style);
-  paint.setColor(0xFFFFFFFF);
-  canvas_->drawRectCoords(left, top, left + width, top + height, paint);
-  isDirty_ = true;
-}
-
diff --git a/runtime/embedders/openglui/common/canvas_context.h b/runtime/embedders/openglui/common/canvas_context.h
deleted file mode 100644
index a45b574..0000000
--- a/runtime/embedders/openglui/common/canvas_context.h
+++ /dev/null
@@ -1,324 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_
-#define EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_
-
-#include "embedders/openglui/common/canvas_state.h"
-#include "embedders/openglui/common/graphics_handler.h"
-#include "embedders/openglui/common/log.h"
-#include "embedders/openglui/common/opengl.h"
-#include "embedders/openglui/common/support.h"
-
-typedef struct ImageData {
-  int width;
-  int height;
-  GLubyte* pixels;
-
-  ImageData(int wp, int hp, GLubyte* pp)
-    : width(wp), height(hp), pixels(pp) {
-  }
-  ImageData()
-    : width(0), height(0), pixels(NULL) {
-  }
-} ImageData;
-
-class CanvasContext {
- protected:
-  SkCanvas* canvas_;
-  int16_t width_, height_;
-  bool imageSmoothingEnabled_;
-  bool isDirty_;
-  CanvasState* state_;
-
-  static inline float Radians2Degrees(float angle) {
-    return 180.0 * angle / M_PI;
-  }
-
-  inline void NotImplemented(const char* method) {
-    LOGE("Method CanvasContext::%s is not yet implemented", method);
-  }
-
- public:
-  CanvasContext(int handle, int16_t width, int16_t height);
-  virtual ~CanvasContext();
-
-  inline bool isDirty() {
-    return isDirty_;
-  }
-
-  inline void clearDirty() {
-    isDirty_ = false;
-  }
-
-  inline void setGlobalAlpha(float alpha) {
-    state_->setGlobalAlpha(alpha);
-  }
-
-  inline void setFillColor(const char* color) {
-    state_->setFillColor(color);
-  }
-
-  inline void setStrokeColor(const char* color) {
-    state_->setStrokeColor(color);
-  }
-
-  inline void setShadowBlur(float blur) {
-    state_->setShadowBlur(blur);
-  }
-
-  inline void setShadowColor(const char* color) {
-    state_->setShadowColor(color);
-  }
-
-  inline void setShadowOffsetX(float offset) {
-    state_->setShadowOffsetX(offset);
-  }
-
-  inline void setShadowOffsetY(float offset) {
-    state_->setShadowOffsetY(offset);
-  }
-
-  // For now, we don't allow resizing.
-  // TODO(gram): fix this or remove these.
-  inline int setWidth(int widthp) {
-    return width_;
-  }
-
-  inline int setHeight(int heightp) {
-    return height_;
-  }
-
-  inline bool imageSmoothingEnabled() {
-    return imageSmoothingEnabled_;
-  }
-
-  inline void setImageSmoothingEnabled(bool enabled) {
-    // TODO(gram): We're not actually doing anything with this yet.
-    imageSmoothingEnabled_ = enabled;
-  }
-
-  inline void setGlobalCompositeOperation(const char* op) {
-    state_->setGlobalCompositeOperation(op);
-  }
-
-  void Save();
-  void Restore();
-
-  inline void Rotate(float angle) {
-    canvas_->rotate(Radians2Degrees(angle));
-  }
-
-  inline void Translate(float x, float y) {
-    canvas_->translate(x, y);
-  }
-
-  inline void Scale(float x, float y) {
-    canvas_->scale(x, y);
-  }
-
-  inline void Transform(float a, float b,
-                        float c, float d,
-                        float e, float f) {
-    SkMatrix t;
-    // Our params are for a 3 x 2 matrix in column order:
-    //
-    // a c e
-    // b d f
-    //
-    // We need to turn this into a 3x3 matrix:
-    //
-    // a c e
-    // b d f
-    // 0 0 1
-    //
-    // and pass the params in row order:
-    t.setAll(a, c, e, b, d, f, 0, 0, 1);
-    canvas_->concat(t);
-  }
-
-  inline void setTransform(float a, float b,
-                           float c, float d,
-                           float e, float f) {
-    SkMatrix t;
-    t.setAll(a, c, e, b, d, f, 0, 0, 1);
-    canvas_->setMatrix(t);
-  }
-
-  ImageData* GetImageData(float sx, float sy, float sw, float sh) {
-    NotImplemented("GetImageData");
-    return NULL;
-  }
-
-  void PutImageData(ImageData* imageData, float  dx, float dy) {
-    NotImplemented("PutImageData");
-  }
-
-  void DrawImage(const char* src_url,
-                 int sx, int sy, bool has_src_dimensions, int sw, int sh,
-                 int dx, int dy, bool has_dst_dimensions, int dw, int dh);
-
-  inline void Clear() {
-    canvas_->drawColor(0xFFFFFFFF);
-    isDirty_ = true;
-  }
-
-  void ClearRect(float left, float top, float width, float height);
-
-  inline void FillRect(float left, float top, float width, float height) {
-    // Does not affect the path.
-    state_->FillRect(left, top, width, height);
-    isDirty_ = true;
-  }
-
-  inline void StrokeRect(float left, float top, float width, float height) {
-    // Does not affect the path.
-    state_->StrokeRect(left, top, width, height);
-    isDirty_ = true;
-  }
-
-  inline void BeginPath() {
-    state_->BeginPath();
-  }
-
-  inline void Fill() {
-    state_->Fill();
-    isDirty_ = true;
-  }
-
-  inline void Stroke() {
-    state_->Stroke();
-    isDirty_ = true;
-  }
-
-  inline void ClosePath() {
-    state_->ClosePath();
-  }
-
-  inline void MoveTo(float x, float y) {
-    state_->MoveTo(x, y);
-  }
-
-  inline void LineTo(float x, float y) {
-    state_->LineTo(x, y);
-  }
-
-  inline void QuadraticCurveTo(float cpx, float cpy, float x, float y) {
-    state_->QuadraticCurveTo(cpx, cpy, x, y);
-  }
-
-  inline void BezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y,
-                     float x, float y) {
-    state_->BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
-  }
-
-  inline void ArcTo(float x1, float y1, float x2, float y2, float radius) {
-    state_->ArcTo(x1, y1, x2, y2, radius);
-  }
-
-  inline void Rect(float x, float y, float w, float h) {
-    state_->Rect(x, y, w, h);
-  }
-
-  inline void Arc(float x, float y, float radius,
-                  float startAngle, float endAngle,
-                  bool antiClockwise) {
-    state_->Arc(x, y, radius, startAngle, endAngle, antiClockwise);
-  }
-
-  inline void setLineWidth(double w) {
-    state_->setLineWidth(w);
-  }
-
-  inline void setLineCap(const char* lc) {
-    state_->setLineCap(lc);
-  }
-
-  inline void setLineDash(float* dashes, int len) {
-    state_->setLineDash(dashes, len);
-  }
-
-  inline void setLineDashOffset(float offset) {
-    state_->setLineDashOffset(offset);
-  }
-
-  inline void setLineJoin(const char* lj) {
-    state_->setLineJoin(lj);
-  }
-
-  inline void setMiterLimit(float limit) {
-    state_->setMiterLimit(limit);
-  }
-
-  inline const char* setFont(const char* font) {
-    return state_->setFont(font);
-  }
-
-  inline const char* setTextAlign(const char* align) {
-    return state_->setTextAlign(align);
-  }
-
-  const char* setTextBaseline(const char* baseline) {
-    return state_->setTextBaseline(baseline);
-  }
-
-  inline const char* setDirection(const char* direction) {
-    return state_->setTextDirection(direction);
-  }
-
-  inline void FillText(const char* text, float x, float y,
-                       float maxWidth = -1) {
-    state_->FillText(text, x, y, maxWidth);
-    isDirty_ = true;
-  }
-
-  inline void StrokeText(const char* text, float x, float y,
-                         float maxWidth = -1) {
-    state_->StrokeText(text, x, y, maxWidth);
-    isDirty_ = true;
-  }
-
-  inline float MeasureText(const char *text) {
-    return state_->MeasureText(text);
-  }
-
-  inline void Clip() {
-    state_->Clip();
-  }
-
-  inline void ResetClip() {
-    // TODO(gram): Check this. Is it affected by the transform?
-    canvas_->clipRect(SkRect::MakeLTRB(0, 0, width_, height_),
-                      SkRegion::kReplace_Op);
-  }
-
-  virtual void Flush() {
-    canvas_->flush();
-  }
-
-  inline void SetFillGradient(bool is_radial, double x0, double y0, double r0,
-      double x1, double y1, double r1,
-      int stops, float* positions, char** colors) {
-    state_->SetFillGradient(is_radial, x0, y0, r0, x1, y1, r1,
-        stops, positions, colors);
-  }
-
-  inline void SetStrokeGradient(bool is_radial, double x0, double y0, double r0,
-      double x1, double y1, double r1,
-      int stops, float* positions, char** colors) {
-    state_->SetStrokeGradient(is_radial, x0, y0, r0, x1, y1, r1,
-        stops, positions, colors);
-  }
-
-  inline const SkBitmap* GetBitmap() {
-    SkDevice* device = canvas_->getDevice();
-    return &device->accessBitmap(false);
-  }
-};
-
-CanvasContext* Context2D(int handle);
-void FreeContexts();
-
-#endif  // EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_
-
diff --git a/runtime/embedders/openglui/common/canvas_state.cc b/runtime/embedders/openglui/common/canvas_state.cc
deleted file mode 100644
index 8d927c8..0000000
--- a/runtime/embedders/openglui/common/canvas_state.cc
+++ /dev/null
@@ -1,411 +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.
-
-#include "embedders/openglui/common/canvas_state.h"
-
-#include <ctype.h>
-#include <string.h>
-
-#include "embedders/openglui/common/support.h"
-
-// Float parser. Does not handle exponents. This is
-// used to parse font sizes so it doesn't need to be full-blown.
-float ParseFloat(const char* s, int& pos) {
-  int len = strlen(s);
-  float rtn = 0.0;
-  while (pos < len && s[pos] != '.' && !isdigit(s[pos])) {
-    ++pos;
-  }
-  while (pos < len && isdigit(s[pos])) {
-    rtn = rtn * 10.0 + s[pos] - '0';
-    ++pos;
-  }
-  if (pos < len && s[pos] == '.') {
-    pos++;
-    float div = 1.0;
-    while (pos < len && isdigit(s[pos])) {
-      rtn = rtn * 10.0 + s[pos] - '0';
-      ++pos;
-      div *= 10.0;
-    }
-    rtn /= div;
-  }
-  return rtn;
-}
-
-int ParseInt(const char* s, int& pos) {
-  int len = strlen(s);
-  int rtn = 0;
-  while (pos < len && !isdigit(s[pos])) {
-    ++pos;
-  }
-  while (pos < len && isdigit(s[pos])) {
-    rtn = rtn * 10 + s[pos] - '0';
-    ++pos;
-  }
-  return rtn;
-}
-
-CanvasState* CanvasState::Restore() {
-  if (next_ != NULL) {
-    // If the state we are popping has a non-empty path,
-    // apply the state's transform to the path, then
-    // add the path to the previous state's path.
-    if (path_->countPoints() > 0) {
-      path_->transform(canvas_->getTotalMatrix());
-      next_->path_->addPath(*path_);
-    }
-    canvas_->restore();
-    return next_;
-  }
-  canvas_->restore();
-  return next_;  // TODO(gram): Should we assert/throw?
-}
-
-void CanvasState::setLineCap(const char* lc) {
-  if (strcmp(lc, "round") == 0) {
-    paint_.setStrokeCap(SkPaint::kRound_Cap);
-  } else if (strcmp(lc, "square") == 0) {
-    paint_.setStrokeCap(SkPaint::kSquare_Cap);
-  } else {
-    paint_.setStrokeCap(SkPaint::kButt_Cap);
-  }
-}
-
-void CanvasState::setLineJoin(const char* lj) {
-  if (strcmp(lj, "round") == 0) {
-    paint_.setStrokeJoin(SkPaint::kRound_Join);
-  } else if (strcmp(lj, "bevel") == 0) {
-    paint_.setStrokeJoin(SkPaint::kBevel_Join);
-  } else {
-    paint_.setStrokeJoin(SkPaint::kMiter_Join);
-  }
-}
-
-const char* CanvasState::setFont(const char*name, float size) {
-  // Font names have the form "<modifier> <size> <family>".
-  // Modifiers are "normal", "italic", "bold".
-  // Sizes have magnitude and units; e.g. "10pt", "20px".
-  const char* rtn = name;
-  if (size < 0) {
-    int pos = 0;
-    // TODO(gram): need to handle these modifiers.
-    if (strncmp(name, "normal", 6) == 0) {
-      pos = 6;
-    } else if (strncmp(name, "italic", 6) == 0) {
-      pos = 6;
-    } else if (strncmp(name, "bold", 4) == 0) {
-      pos = 4;
-    }
-    size = ParseFloat(name, pos);
-    // Font size units: px, etc. For now just px.
-    // TODO(gram): Handle other units.
-    if (strncmp(name + pos, "px", 2) == 0) {
-      pos += 2;
-    }
-    int len = strlen(name);
-    while (pos < len && isspace(name[pos])) {
-      ++pos;
-    }
-    name = name + pos;
-  }
-  SkTypeface *pTypeface = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
-  paint_.setTypeface(pTypeface);
-  paint_.setTextSize(size);
-  // TODO(gram): Must return a normalized font name incorporating size, so
-  // callers can set the Dart canvas font name to an appropriate value.
-  // Actually this may not be necessary in which case we can change this
-  // method to return void.
-  return rtn;
-}
-
-const char* CanvasState::setTextAlign(const char* align) {
-  // TODO(gram): What about "start" and "end"?
-  // I don't see any an analogs in Skia.
-  if (strcmp(align, "left") == 0) {
-    paint_.setTextAlign(SkPaint::kLeft_Align);
-  } else if (strcmp(align, "right") == 0) {
-    paint_.setTextAlign(SkPaint::kRight_Align);
-  } else {
-    paint_.setTextAlign(SkPaint::kCenter_Align);
-  }
-  return align;
-}
-
-const char* CanvasState::setTextBaseline(const char* baseline) {
-  // TODO(gram): Does skia support this? It doesn't seem like
-  // it. Right now we don't use the textBaseline value, but we
-  // may have to implement this ourselves, by adjusting the y
-  // values passed to StrokeText/FillText using the font metrics.
-  if (strcmp(baseline, "top") == 0) {
-  } else if (strcmp(baseline, "middle") == 0) {
-  } else if (strcmp(baseline, "bottom") == 0) {
-  } else if (strcmp(baseline, "hanging") == 0) {
-  } else if (strcmp(baseline, "alphabetic") == 0) {
-  } else if (strcmp(baseline, "ideographic") == 0) {
-  }
-  return baseline;
-}
-
-const char* CanvasState::setTextDirection(const char* direction) {
-    // TODO(gram): Add support for this if Skia does.
-  return direction;
-}
-
-void CanvasState::setMode(SkPaint::Style style, ColorRGBA color,
-    SkShader* shader) {
-  paint_.setStyle(style);
-  paint_.setColor(color.v);
-  paint_.setShader(shader);
-  uint8_t alpha = static_cast<uint8_t>(
-      globalAlpha_ * static_cast<float>(color.alpha()));
-  paint_.setAlpha(alpha);
-  bool drawShadow = (shadowOffsetX_ != 0 ||
-                     shadowOffsetY_ != 0 ||
-                     shadowBlur_ != 0) &&
-                     shadowColor_.alpha() > 0;
-  if (drawShadow) {
-    // TODO(gram): should we mult shadowColor by globalAlpha?
-    paint_.setLooper(new SkBlurDrawLooper(SkFloatToScalar(shadowBlur_),
-                                          SkFloatToScalar(shadowOffsetX_),
-                                          SkFloatToScalar(shadowOffsetY_),
-                                          shadowColor_.v))->unref();
-  } else {
-    paint_.setLooper(NULL);
-  }
-}
-
-void CanvasState::setGlobalCompositeOperation(const char* op) {
-  SkXfermode::Mode mode;
-  static const struct CompositOpToXfermodeMode {
-    const char* mCompositOp;
-    uint8_t m_xfermodeMode;
-  } gMapCompositOpsToXfermodeModes[] = {
-     { "clear",            SkXfermode::kClear_Mode },
-     { "copy",             SkXfermode::kSrc_Mode },
-     { "source-over",      SkXfermode::kSrcOver_Mode },
-     { "source-in",        SkXfermode::kSrcIn_Mode },
-     { "source-out",       SkXfermode::kSrcOut_Mode },
-     { "source-atop",      SkXfermode::kSrcATop_Mode },
-     { "destination-over", SkXfermode::kDstOver_Mode },
-     { "destination-in",   SkXfermode::kDstIn_Mode },
-     { "destination-out",  SkXfermode::kDstOut_Mode },
-     { "destination-atop", SkXfermode::kDstATop_Mode },
-     { "xor",              SkXfermode::kXor_Mode },
-     { "darker",           SkXfermode::kDarken_Mode },
-     { "lighter",          SkXfermode::kPlus_Mode }
-  };
-  for (unsigned i = 0;
-       i < SK_ARRAY_COUNT(gMapCompositOpsToXfermodeModes);
-       i++) {
-    if (strcmp(op, gMapCompositOpsToXfermodeModes[i].mCompositOp) == 0) {
-      mode = (SkXfermode::Mode)gMapCompositOpsToXfermodeModes[i].m_xfermodeMode;
-      paint_.setXfermodeMode(mode);
-      return;
-    }
-  }
-  LOGE("Unknown CompositeOperator %s\n", op);
-  paint_.setXfermodeMode(SkXfermode::kSrcOver_Mode);  // fall-back
-}
-
-void CanvasState::Arc(float x, float y, float radius,
-                      float startAngle, float endAngle,
-                      bool antiClockwise) {
-  SkRect rect;
-  rect.set(x - radius, y - radius, x + radius, y + radius);
-  bool doCircle = false;
-
-  static float twoPi = 2 * M_PI;
-
-  float sweep = endAngle - startAngle;
-  if (sweep >= twoPi || sweep <= -twoPi) {
-    doCircle = true;
-  }
-
-  if (!antiClockwise && endAngle <= startAngle) {
-    endAngle += 2 * M_PI;
-  } else if (antiClockwise && startAngle <= endAngle) {
-    startAngle += 2 * M_PI;
-  }
-  sweep = endAngle - startAngle;
-
-  startAngle = fmodf(startAngle, twoPi);
-  float sa = Radians2Degrees(startAngle);
-  float ea = Radians2Degrees(sweep);
-  path_->arcTo(rect, sa, ea, false);
-  if (doCircle) {
-    SkPath tmp;
-    tmp.addOval(rect);
-    tmp.addPath(*path_);
-    path_->swap(tmp);
-  }
-}
-
-int hexDigit(char c) {
-  if (c >= '0' && c <= '9') return c - '0';
-  if (c <= 'Z') return c - 'A' + 10;
-  return c - 'a' + 10;
-}
-
-// Color parser.
-// See http://www.w3.org/TR/CSS21/syndata.html#color-units.
-// There is also another format: hsl(240,100%,100%) (and hsla)
-// TODO(gram): We probably eventually want to use a table rather
-// than a big if statement; see setGlobalCompositeOperation for
-// an example.
-ColorRGBA CanvasState::GetColor(const char* color) {
-  if (color[0] == '#') {
-    int r = 0, g = 0, b = 0;
-    if (strlen(color) == 7) {
-      r = hexDigit(color[1]) * 16 + hexDigit(color[2]);
-      g = hexDigit(color[3]) * 16 + hexDigit(color[4]);
-      b = hexDigit(color[5]) * 16 + hexDigit(color[6]);
-    } else if (strlen(color) == 4) {
-      r = hexDigit(color[1]) * 16 + hexDigit(color[1]);
-      g = hexDigit(color[2]) * 16 + hexDigit(color[2]);
-      b = hexDigit(color[3]) * 16 + hexDigit(color[3]);
-    }
-    return ColorRGBA(r, g, b);
-  } else if (strcmp(color, "maroon") == 0) {
-    return ColorRGBA(0x80, 0x00, 0x00);
-  } else if (strcmp(color, "red") == 0) {
-    return ColorRGBA(0xFF, 0x00, 0x00);
-  } else if (strcmp(color, "orange") == 0) {
-    return ColorRGBA(0xFF, 0xA5, 0x00);
-  } else if (strcmp(color, "yellow") == 0) {
-    return ColorRGBA(0xFF, 0xFF, 0x00);
-  } else if (strcmp(color, "olive") == 0) {
-    return ColorRGBA(0x80, 0x80, 0x00);
-  } else if (strcmp(color, "purple") == 0) {
-    return ColorRGBA(0x80, 0x00, 0x80);
-  } else if (strcmp(color, "fuschia") == 0) {
-    return ColorRGBA(0xFF, 0x00, 0xFF);
-  } else if (strcmp(color, "white") == 0) {
-    return ColorRGBA(0xFF, 0xFF, 0xFF);
-  } else if (strcmp(color, "lime") == 0) {
-    return ColorRGBA(0x00, 0xFF, 0x00);
-  } else if (strcmp(color, "green") == 0) {
-    return ColorRGBA(0x00, 0x80, 0x00);
-  } else if (strcmp(color, "navy") == 0) {
-    return ColorRGBA(0x00, 0x00, 0x80);
-  } else if (strcmp(color, "blue") == 0) {
-    return ColorRGBA(0x00, 0x00, 0xFF);
-  } else if (strcmp(color, "aqua") == 0) {
-    return ColorRGBA(0x00, 0xFF, 0xFF);
-  } else if (strcmp(color, "teal") == 0) {
-    return ColorRGBA(0x00, 0x80, 0x80);
-  } else if (strcmp(color, "silver") == 0) {
-    return ColorRGBA(0xC0, 0xC0, 0xC0);
-  } else if (strcmp(color, "gray") == 0) {
-    return ColorRGBA(0x80, 0x80, 0x80);
-  } else if (strncmp(color, "rgb(", 4) == 0) {
-    int pos = 4;
-    int r = ParseInt(color, pos);
-    ++pos;
-    int g = ParseInt(color, pos);
-    ++pos;
-    int b = ParseInt(color, pos);
-    return ColorRGBA(r, g, b);
-  } else if (strncmp(color, "rgba(", 5) == 0) {
-    int pos = 5;
-    int r = ParseInt(color, pos);
-    ++pos;
-    int g = ParseInt(color, pos);
-    ++pos;
-    int b = ParseInt(color, pos);
-    ++pos;
-    float a = ParseFloat(color, pos);
-    return ColorRGBA(r, g, b, static_cast<int>(a * 255.0));
-  }
-  // Default to black.
-  return ColorRGBA(0x00, 0x00, 0x00);
-}
-
-void CanvasState::DrawImage(const SkBitmap& bm,
-                            int sx, int sy, int sw, int sh,
-                            int dx, int dy, int dw, int dh) {
-  if (sw < 0) sw = bm.width();
-  if (dw < 0) dw = bm.width();
-  if (sh < 0) sh = bm.height();
-  if (dh < 0) dh = bm.height();
-  SkIRect src = SkIRect::MakeXYWH(sx, sy, sw, sh);
-  SkRect dst = SkRect::MakeXYWH(dx, dy, dw, dh);
-  LOGI("DrawImage(_,%d,%d,%d,%d,%d,%d,%d,%d)", sx, sy, sw, sh, dx, dy, dw, dh);
-  canvas_->drawBitmapRect(bm, &src, dst);
-}
-
-void CanvasState::SetFillGradient(bool is_radial,
-    double x0, double y0, double r0,
-    double x1, double y1, double r1,
-    int stops, float* positions, char** colors) {
-  if (fillShader_ != NULL) {
-    fillShader_->unref();
-  }
-  if (is_radial) {
-    fillShader_ = CreateRadialGradient(x0, y0, r0, x1, y1, r1,
-        stops, positions, colors);
-  } else {
-    fillShader_ = CreateLinearGradient(x0, y0, x1, y1,
-        stops, positions, colors);
-  }
-  fillShader_->validate();
-}
-
-void CanvasState::SetStrokeGradient(bool is_radial,
-    double x0, double y0, double r0,
-    double x1, double y1, double r1,
-    int stops, float* positions, char** colors) {
-  if (strokeShader_ != NULL) {
-    strokeShader_->unref();
-  }
-  if (is_radial) {
-    strokeShader_ = CreateRadialGradient(x0, y0, r0, x1, y1, r1,
-        stops, positions, colors);
-  } else {
-    strokeShader_ = CreateLinearGradient(x0, y0, x1, y1,
-        stops, positions, colors);
-  }
-  strokeShader_->validate();
-}
-
-SkShader* CanvasState::CreateRadialGradient(
-      double x0, double y0, double r0,
-      double x1, double y1, double r1,
-      int stops, float* positions, char** colors) {
-  SkScalar* p = new SkScalar[stops];
-  SkColor* c = new SkColor[stops];
-  for (int i = 0; i < stops; i++) {
-    p[i] = positions[i];
-    c[i] = GetColor(colors[i]).v;
-  }
-  LOGI("CreateRadialGradient(%f,%f,%f,%f,%f,%f,%d,[%f,%f],[%s,%s]",
-    x0, y0, r0, x1, y1, r1, stops, positions[0], positions[1],
-    colors[0], colors[1]);
-  SkShader* shader = SkGradientShader::CreateTwoPointRadial(
-      SkPoint::Make(x0, y0), r0, SkPoint::Make(x1, y1), r1,
-      c, p, stops, SkShader::kClamp_TileMode);
-  delete[] c;
-  delete[] p;
-  return shader;
-}
-
-SkShader* CanvasState::CreateLinearGradient(
-      double x0, double y0, double x1, double y1,
-      int stops, float* positions, char** colors) {
-  SkScalar* p = new SkScalar[stops];
-  SkColor* c = new SkColor[stops];
-  for (int i = 0; i < stops; i++) {
-    p[i] = positions[i];
-    c[i] = GetColor(colors[i]).v;
-  }
-  SkPoint pts[2];
-  pts[0] = SkPoint::Make(x0, y0);
-  pts[1] = SkPoint::Make(x1, y1);
-  SkShader* shader =  SkGradientShader::CreateLinear(pts, c, p, stops,
-      SkShader::kClamp_TileMode);
-  delete[] c;
-  delete[] p;
-  return shader;
-}
-
diff --git a/runtime/embedders/openglui/common/canvas_state.h b/runtime/embedders/openglui/common/canvas_state.h
deleted file mode 100644
index fc0e095..0000000
--- a/runtime/embedders/openglui/common/canvas_state.h
+++ /dev/null
@@ -1,312 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_
-#define EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_
-
-#include "embedders/openglui/common/graphics_handler.h"
-#include "embedders/openglui/common/log.h"
-#include "embedders/openglui/common/opengl.h"
-#include "embedders/openglui/common/support.h"
-
-typedef struct CanvasState {
-  SkPaint paint_;
-  float globalAlpha_;
-  float miterLimit_;
-  ColorRGBA fillColor_;
-  ColorRGBA strokeColor_;
-  ColorRGBA shadowColor_;
-  float shadowBlur_;
-  float shadowOffsetX_;
-  float shadowOffsetY_;
-  float* lineDash_;
-  int lineDashCount_;
-  int lineDashOffset_;
-  SkShader* fillShader_;
-  SkShader* strokeShader_;
-
-  SkPath* path_;
-  SkCanvas* canvas_;
-  CanvasState* next_;  // For stack.
-
-  CanvasState(SkCanvas* canvas)
-    : paint_(),
-      globalAlpha_(1.0),
-      miterLimit_(10),
-      fillColor_(ColorRGBA(255, 0, 0, 255)),
-      strokeColor_(fillColor_),
-      shadowColor_(ColorRGBA(0, 0, 0, 0)),
-      shadowBlur_(0.0),
-      shadowOffsetX_(0.0),
-      shadowOffsetY_(0.0),
-      lineDash_(NULL),
-      lineDashCount_(0),
-      lineDashOffset_(0),
-      fillShader_(NULL),
-      strokeShader_(NULL),
-      path_(new SkPath()),
-      canvas_(canvas),
-      next_(NULL) {
-    paint_.setStrokeCap(SkPaint::kButt_Cap);
-    paint_.setStrokeJoin(SkPaint::kMiter_Join);
-    paint_.setStrokeWidth(1);
-    paint_.setTextAlign(SkPaint::kLeft_Align);
-    paint_.setAntiAlias(true);
-    paint_.setStyle(SkPaint::kStroke_Style);
-    setFont("Helvetica", 10);
-  }
-
-  CanvasState(const CanvasState& state)
-    : paint_(state.paint_),
-      globalAlpha_(state.globalAlpha_),
-      miterLimit_(state.miterLimit_),
-      fillColor_(state.fillColor_),
-      strokeColor_(state.strokeColor_),
-      shadowColor_(state.shadowColor_),
-      shadowBlur_(state.shadowBlur_),
-      shadowOffsetX_(state.shadowOffsetX_),
-      shadowOffsetY_(state.shadowOffsetY_),
-      lineDash_(NULL),
-      lineDashCount_(state.lineDashCount_),
-      lineDashOffset_(state.lineDashOffset_),
-      fillShader_(state.fillShader_),
-      strokeShader_(state.strokeShader_),
-      path_(new SkPath()),
-      canvas_(state.canvas_),
-      next_(NULL) {
-    setLineDash(state.lineDash_, lineDashCount_);
-    if (fillShader_ != NULL) fillShader_->ref();
-    if (strokeShader_ != NULL) strokeShader_->ref();
-  }
-
-  ~CanvasState() {
-    if (fillShader_ != NULL) fillShader_->unref();
-    if (strokeShader_ != NULL) strokeShader_->unref();
-    delete path_;
-    delete[] lineDash_;
-  }
-
-  static ColorRGBA GetColor(const char* color);
-
-  inline CanvasState* Save() {
-    canvas_->save();  // For clip and transform.
-    CanvasState *new_state = new CanvasState(*this);
-    new_state->next_ = this;
-    // If the old state has a non-empty path, use its
-    // last point as the new states first point.
-    int np = path_->countPoints();
-    if (np > 0) {
-      new_state->path_->moveTo(path_->getPoint(np-1));
-    }
-    return new_state;
-  }
-
-  CanvasState* Restore();
-
-  inline float Radians2Degrees(float angle) {
-    return 180.0 * angle / M_PI;
-  }
-
-  inline void setGlobalAlpha(float alpha) {
-    globalAlpha_ = alpha;
-  }
-
-  inline void setFillColor(const char* color) {
-    if (fillShader_ != NULL) {
-      fillShader_->unref();
-      fillShader_ = NULL;
-    }
-    fillColor_ = GetColor(color);
-  }
-
-  inline void setStrokeColor(const char* color) {
-    if (strokeShader_ != NULL) {
-      strokeShader_->unref();
-      strokeShader_ = NULL;
-    }
-    strokeColor_ = GetColor(color);
-  }
-
-  const char* setFont(const char*name, float size = -1);
-  void setLineCap(const char* lc);
-  void setLineJoin(const char* lj);
-
-  inline void setMiterLimit(float limit) {
-    miterLimit_ = limit;
-  }
-
-  const char* setTextAlign(const char* align);
-  const char* setTextBaseline(const char* baseline);
-  const char* setTextDirection(const char* direction);
-
-  inline void FillText(const char* text, float x, float y, float maxWidth) {
-    setFillMode();
-    canvas_->drawText(text, strlen(text), x, y, paint_);
-  }
-
-  inline void StrokeText(const char* text, float x, float y, float maxWidth) {
-    setStrokeMode();
-    canvas_->drawText(text, strlen(text), x, y, paint_);
-  }
-
-  inline float MeasureText(const char *text) {
-    // TODO(gram): make sure this is not supposed to be affected
-    // by the canvas transform.
-    return paint_.measureText(text, strlen(text));
-  }
-
-  inline void setLineWidth(float w) {
-    paint_.setStrokeWidth(w);
-  }
-
-  void setMode(SkPaint::Style style, ColorRGBA color, SkShader* shader);
-
-  inline void setLineDashEffect() {
-    if (lineDashCount_ > 0) {
-      SkDashPathEffect* dashPathEffect =
-        new SkDashPathEffect(lineDash_, lineDashCount_, lineDashOffset_);
-        paint_.setPathEffect(dashPathEffect)->unref();
-    } else {
-      paint_.setPathEffect(NULL);
-    }
-  }
-
-  inline void setLineDash(float* dashes, int len) {
-    if (len == 0) {
-      lineDashCount_ = 0;
-      delete[] lineDash_;
-      lineDash_ = NULL;
-    } else {
-      lineDash_ = new float[lineDashCount_ = len];
-      for (int i = 0; i < len; i++) {
-        lineDash_[i] = dashes[i];
-      }
-    }
-    setLineDashEffect();
-  }
-
-  inline void setLineDashOffset(int offset) {
-    if (offset != lineDashOffset_) {
-      lineDashOffset_ = offset;
-      setLineDashEffect();
-    }
-  }
-
-  inline void setShadowColor(const char* color) {
-    shadowColor_ = GetColor(color);
-  }
-
-  inline void setShadowBlur(float blur) {
-    shadowBlur_ = blur;
-  }
-
-  inline void setShadowOffsetX(float ox) {
-    shadowOffsetX_ = ox;
-  }
-
-  inline void setShadowOffsetY(float oy) {
-    shadowOffsetY_ = oy;
-  }
-
-  inline void setFillMode() {
-    setMode(SkPaint::kFill_Style, fillColor_, fillShader_);
-  }
-
-  inline void setStrokeMode() {
-    setMode(SkPaint::kStroke_Style, strokeColor_, strokeShader_);
-  }
-
-  inline void FillRect(float left, float top,
-                       float width, float height) {
-    // Does not affect the path.
-    setFillMode();
-    canvas_->drawRectCoords(left, top, left + width, top + height, paint_);
-  }
-
-  inline void StrokeRect(float left, float top,
-                         float width, float height) {
-    // Does not affect the path.
-    setStrokeMode();
-    canvas_->drawRectCoords(left, top, left + width, top + height, paint_);
-  }
-
-  inline void BeginPath() {
-    path_->rewind();
-  }
-
-  inline void Fill() {
-    setFillMode();
-    canvas_->drawPath(*path_, paint_);
-  }
-
-  inline void Stroke() {
-    setStrokeMode();
-    canvas_->drawPath(*path_, paint_);
-  }
-
-  inline void ClosePath() {
-    path_->close();
-  }
-
-  inline void MoveTo(float x, float y) {
-    path_->moveTo(x, y);
-  }
-
-  inline void LineTo(float x, float y) {
-    path_->lineTo(x, y);
-  }
-
-  void Arc(float x, float y, float radius, float startAngle, float endAngle,
-           bool antiClockwise);
-
-  inline void QuadraticCurveTo(float cpx, float cpy, float x, float y) {
-    path_->quadTo(cpx, cpy, x, y);
-  }
-
-  inline void BezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y,
-                     float x, float y) {
-    path_->cubicTo(cp1x, cp1y, cp2x, cp2y, x, y);
-  }
-
-  inline void ArcTo(float x1, float y1, float x2, float y2, float radius) {
-    path_->arcTo(x1, y1, x2, y2, radius);
-  }
-
-  inline void Rect(float x, float y, float w, float h) {
-    // TODO(gram): Should we draw this directly? If so, what happens with the
-    // path?
-    path_->addRect(x, y, x + w, y + h);
-  }
-
-  void setGlobalCompositeOperation(const char* op);
-
-  void DrawImage(const SkBitmap& bm,
-                 int sx, int sy, int sw, int sh,
-                 int dx, int dy, int dw, int dh);
-
-  inline void Clip() {
-    canvas_->clipPath(*path_);
-  }
-
-  void SetFillGradient(bool is_radial, double x0, double y0, double r0,
-      double x1, double y1, double r1,
-      int stops, float* positions, char** colors);
-
-  void SetStrokeGradient(bool is_radial, double x0, double y0, double r0,
-      double x1, double y1, double r1,
-      int stops, float* positions, char** colors);
-
- private:
-  SkShader* CreateRadialGradient(
-      double x0, double y0, double r0,
-      double x1, double y1, double r1,
-      int stops, float* positions, char** colors);
-
-  SkShader* CreateLinearGradient(
-      double x0, double y0, double x1, double y1,
-      int stops, float* positions, char** colors);
-} CanvasState;
-
-#endif  // EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_
-
diff --git a/runtime/embedders/openglui/common/context.h b/runtime/embedders/openglui/common/context.h
deleted file mode 100644
index 54148fc..0000000
--- a/runtime/embedders/openglui/common/context.h
+++ /dev/null
@@ -1,23 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_
-#define EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_
-
-#include "embedders/openglui/common/graphics_handler.h"
-#include "embedders/openglui/common/input_handler.h"
-#include "embedders/openglui/common/sound_handler.h"
-#include "embedders/openglui/common/timer.h"
-#include "embedders/openglui/common/vm_glue.h"
-
-struct Context {
-  GraphicsHandler* graphics_handler;
-  InputHandler* input_handler;
-  SoundHandler* sound_handler;
-  Timer* timer;
-  VMGlue* vm_glue;
-};
-
-#endif  // EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_
-
diff --git a/runtime/embedders/openglui/common/dart_host.cc b/runtime/embedders/openglui/common/dart_host.cc
deleted file mode 100644
index dd2c1cd..0000000
--- a/runtime/embedders/openglui/common/dart_host.cc
+++ /dev/null
@@ -1,117 +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.
-
-#include "embedders/openglui/common/dart_host.h"
-
-#include <math.h>
-#include <unistd.h>
-
-#include "embedders/openglui/common/image_cache.h"
-#include "embedders/openglui/common/log.h"
-
-DartHost::DartHost(Context *context)
-    : graphics_handler_(context->graphics_handler),
-      input_handler_(context->input_handler),
-      sound_handler_(context->sound_handler),
-      timer_(context->timer),
-      vm_glue_(context->vm_glue),
-      has_context_(false),
-      started_(false),
-      active_(false) {
-  ImageCache::Init(graphics_handler_->resource_path());
-}
-
-DartHost::~DartHost() {
-}
-
-int32_t DartHost::OnStart() {
-  int result = vm_glue_->StartMainIsolate();
-  if (result != 0) {
-    LOGE("startMainIsolate returned %d", result);
-    return -1;
-  }
-  started_ = true;
-  return 0;
-}
-
-int32_t DartHost::Activate() {
-  if (!has_context_) {
-    if (graphics_handler_->Start() != 0) {
-      return -1;
-    }
-    if (sound_handler_->Start() != 0) {
-      graphics_handler_->Stop();
-      return -1;
-    }
-    if (input_handler_->Start() != 0) {
-      sound_handler_->Stop();
-      graphics_handler_->Stop();
-      return -1;
-    }
-    int32_t rtn = vm_glue_->CallSetup(true);
-    timer_->Reset();
-    has_context_ = true;
-    return rtn;
-  }
-  return 0;
-}
-
-void DartHost::Deactivate() {
-  Pause();
-  if (has_context_) {
-    vm_glue_->CallShutdown();
-    input_handler_->Stop();
-    sound_handler_->Stop();
-    graphics_handler_->Stop();
-    has_context_ = false;
-  }
-}
-
-int32_t DartHost::OnStep() {
-  if (active_) {
-    timer_->Update();
-    if (vm_glue_->CallUpdate() != 0 ||
-        graphics_handler_->Update() != 0) {
-      return -1;
-    }
-  }
-  return 0;
-}
-
-int32_t DartHost::Resume() {
-  if (!active_) {
-    if (Activate() == 0) {
-      sound_handler_->Resume();
-      active_ = true;
-    }
-  }
-  return 0;
-}
-
-void DartHost::Pause() {
-  if (active_) {
-    active_ = false;  // This stops update() calls.
-    sound_handler_->Suspend();
-  }
-}
-
-void DartHost::FreeAllResources() {
-  if (started_) {
-    vm_glue_->FinishMainIsolate();
-    started_ = false;
-  }
-}
-
-void DartHost::OnSaveState(void** data, size_t* size) {
-  LOGI("Saving DartHost state");
-}
-
-void DartHost::OnConfigurationChanged() {
-  LOGI("DartHost config changed");
-}
-
-void DartHost::OnLowMemory() {
-  LOGI("DartHost low on memory");
-}
-
diff --git a/runtime/embedders/openglui/common/dart_host.h b/runtime/embedders/openglui/common/dart_host.h
deleted file mode 100644
index 9233aa2f..0000000
--- a/runtime/embedders/openglui/common/dart_host.h
+++ /dev/null
@@ -1,47 +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.
-
-#ifndef EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_
-#define EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_
-
-#include "embedders/openglui/common/context.h"
-#include "embedders/openglui/common/graphics_handler.h"
-#include "embedders/openglui/common/input_handler.h"
-#include "embedders/openglui/common/lifecycle_handler.h"
-#include "embedders/openglui/common/sound_handler.h"
-#include "embedders/openglui/common/timer.h"
-#include "embedders/openglui/common/vm_glue.h"
-#include "include/dart_api.h"
-
-class DartHost : public LifeCycleHandler {
- public:
-  explicit DartHost(Context* context);
-  virtual ~DartHost();
-
-  int32_t OnStart();
-  void OnSaveState(void** data, size_t* size);
-  void OnConfigurationChanged();
-  void OnLowMemory();
-  int32_t Activate();
-  void Deactivate();
-  void Pause();
-  int32_t Resume();
-  void FreeAllResources();
-  int32_t OnStep();
-
- private:
-  void Clear();
-
-  GraphicsHandler* graphics_handler_;
-  InputHandler* input_handler_;
-  SoundHandler* sound_handler_;
-  Timer* timer_;
-  VMGlue* vm_glue_;
-  bool has_context_;
-  bool started_;
-  bool active_;
-};
-
-#endif  // EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_
-
diff --git a/runtime/embedders/openglui/common/events.h b/runtime/embedders/openglui/common/events.h
deleted file mode 100644
index 64c6951..0000000
--- a/runtime/embedders/openglui/common/events.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_
-#define EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_
-
-typedef enum {
-  kStart,
-  kStop,
-  kGainedFocus,
-  kLostFocus,
-  kPause,
-  kResume,
-  kSaveState,
-  kConfigChanged,
-  kInitWindow,
-  kTermWindow,
-  kDestroy
-} LifecycleEvent;
-
-typedef enum {
-  kKeyDown,
-  kKeyUp,
-  kKeyMultiple
-} KeyEvent;
-
-typedef enum {
-  kMotionDown,
-  kMotionUp,
-  kMotionMove,
-  kMotionCancel,
-  kMotionOutside,
-  kMotionPointerDown,
-  kMotionPointerUp
-} MotionEvent;
-
-#endif  // EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_
-
diff --git a/runtime/embedders/openglui/common/extension.cc b/runtime/embedders/openglui/common/extension.cc
deleted file mode 100644
index 6304c3b..0000000
--- a/runtime/embedders/openglui/common/extension.cc
+++ /dev/null
@@ -1,1737 +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.
-
-#include "embedders/openglui/common/extension.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "embedders/openglui/common/canvas_context.h"
-#include "embedders/openglui/common/image_cache.h"
-#include "embedders/openglui/common/graphics_handler.h"
-#include "embedders/openglui/common/log.h"
-#include "embedders/openglui/common/opengl.h"
-#include "include/dart_api.h"
-#include "include/dart_native_api.h"
-
-Dart_Handle HandleError(Dart_Handle handle) {
-  if (Dart_IsError(handle)) Dart_PropagateError(handle);
-  return handle;
-}
-
-void CheckGLError(const char *function) {
-  int error = glGetError();
-  if (error != GL_NO_ERROR) {
-    if (error == GL_INVALID_ENUM) {
-      LOGE("%s: An unacceptable value is given for an enumerated argument.",
-           function);
-    } else if (error == GL_INVALID_VALUE) {
-      LOGE("%s: A numeric argument is out of range.", function);
-    } else if (error == GL_INVALID_OPERATION) {
-      LOGE("%s: The specified operation is not allowed in the current state.",
-           function);
-    } else if (error == GL_INVALID_FRAMEBUFFER_OPERATION) {
-      LOGE("%s: The framebuffer object is not complete.", function);
-    } else if (error == GL_OUT_OF_MEMORY) {
-      LOGE("%s: There is not enough memory left to execute the command.",
-          function);
-    } else {
-      LOGE("ERROR!: %s returns %d", function, error);
-    }
-  }
-}
-
-const char* GetArgAsString(Dart_NativeArguments arguments, int idx) {
-  Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, idx));
-  uint8_t* str;
-  intptr_t length;
-  HandleError(Dart_StringLength(handle, &length));
-  HandleError(Dart_StringToUTF8(handle, &str, &length));
-  str[length] = 0;
-  return  const_cast<const char*>(reinterpret_cast<char*>(str));
-}
-
-double GetArgAsDouble(Dart_NativeArguments arguments, int index) {
-  Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index));
-  if (Dart_IsDouble(handle)) {
-    double v;
-    HandleError(Dart_DoubleValue(handle, &v));
-    return v;
-  }
-  if (Dart_IsInteger(handle)) {
-    int64_t v;
-    HandleError(Dart_IntegerToInt64(handle, &v));
-    return static_cast<double>(v);
-  }
-  LOGE("Argument at index %d has non-numeric type", index);
-  Dart_ThrowException(Dart_NewStringFromCString("Numeric argument expected."));
-  return 0;
-}
-
-int64_t GetArgAsInt(Dart_NativeArguments arguments, int index) {
-  Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index));
-  if (Dart_IsDouble(handle)) {
-    double v;
-    HandleError(Dart_DoubleValue(handle, &v));
-    return static_cast<int64_t>(v);
-  }
-  if (Dart_IsInteger(handle)) {
-    int64_t v;
-    HandleError(Dart_IntegerToInt64(handle, &v));
-    return v;
-  }
-  LOGE("Argument at index %d has non-numeric type", index);
-  Dart_ThrowException(Dart_NewStringFromCString("Numeric argument expected."));
-  return 0;
-}
-
-bool GetArgAsBool(Dart_NativeArguments arguments, int index) {
-  Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index));
-  if (Dart_IsBoolean(handle)) {
-    bool v;
-    HandleError(Dart_BooleanValue(handle, &v));
-    return v;
-  }
-  LOGI("Argument at index %d has non-Boolean type", index);
-  Dart_ThrowException(Dart_NewStringFromCString("Boolean argument expected."));
-  return false;
-}
-
-int GetListLength(Dart_NativeArguments arguments, int index,
-    Dart_Handle& argHandle) {
-  argHandle = HandleError(Dart_GetNativeArgument(arguments, index));
-  if (Dart_IsList(argHandle)) {
-    intptr_t len;
-    HandleError(Dart_ListLength(argHandle, &len));
-    return len;
-  }
-  LOGI("Argument at index %d has non-List type", index);
-  Dart_ThrowException(Dart_NewStringFromCString("List argument expected."));
-  return -1;
-}
-
-GLint* GetArgsAsGLintList(Dart_NativeArguments arguments, int index,
-                          int* len_out) {
-  Dart_Handle argHandle;
-  int len = GetListLength(arguments, index, argHandle);
-  if (len < 0) return NULL;
-  GLint* list = new GLint[len];
-  for (int i = 0; i < len; i++) {
-    Dart_Handle vHandle = Dart_ListGetAt(argHandle, i);
-    int64_t v;
-    HandleError(Dart_IntegerToInt64(vHandle, &v));
-    list[i] = v;
-  }
-  *len_out = len;
-  return list;
-}
-
-GLfloat* GetArgsAsFloatList(Dart_NativeArguments arguments, int index,
-                            int* len_out) {
-  Dart_Handle argHandle;
-  int len = GetListLength(arguments, index, argHandle);
-  if (len < 0) return NULL;
-  GLfloat* list = new GLfloat[len];
-  for (int i = 0; i < len; i++) {
-    Dart_Handle vHandle = Dart_ListGetAt(argHandle, i);
-    double v;
-    HandleError(Dart_DoubleValue(vHandle, &v));
-    list[i] = v;
-  }
-  *len_out = len;
-  return list;
-}
-
-char** GetArgsAsStringList(Dart_NativeArguments arguments, int index,
-                            int* len_out) {
-  Dart_Handle argHandle;
-  int len = GetListLength(arguments, index, argHandle);
-  if (len < 0) return NULL;
-  char** list = new char*[len];
-  for (int i = 0; i < len; i++) {
-    Dart_Handle vHandle = Dart_ListGetAt(argHandle, i);
-    uint8_t* str;
-    intptr_t length;
-    HandleError(Dart_StringLength(vHandle, &length));
-    HandleError(Dart_StringToUTF8(vHandle, &str, &length));
-    str[length] = 0;
-    list[i] = reinterpret_cast<char*>(str);
-  }
-  *len_out = len;
-  return list;
-}
-
-void SetBoolReturnValue(Dart_NativeArguments arguments, bool b) {
-  Dart_Handle result = HandleError(Dart_NewBoolean(b));
-  Dart_SetReturnValue(arguments, result);
-}
-
-void SetIntReturnValue(Dart_NativeArguments arguments, int v) {
-  Dart_Handle result = HandleError(Dart_NewInteger(v));
-  Dart_SetReturnValue(arguments, result);
-}
-
-void SetDoubleReturnValue(Dart_NativeArguments arguments, double v) {
-  Dart_Handle result = HandleError(Dart_NewDouble(v));
-  Dart_SetReturnValue(arguments, result);
-}
-
-void SetStringReturnValue(Dart_NativeArguments arguments, const char* s) {
-  Dart_Handle result = HandleError(Dart_NewStringFromCString(s));
-  Dart_SetReturnValue(arguments, result);
-}
-
-void Log(Dart_NativeArguments arguments) {
-  Dart_EnterScope();
-  LOGI("%s", GetArgAsString(arguments, 0));
-  Dart_ExitScope();
-}
-
-void LogError(Dart_NativeArguments arguments) {
-  Dart_EnterScope();
-  LOGE("%s", GetArgAsString(arguments, 0));
-  Dart_ExitScope();
-}
-
-void SystemRand(Dart_NativeArguments arguments) {
-  Dart_EnterScope();
-  SetIntReturnValue(arguments, rand());
-  Dart_ExitScope();
-}
-
-void SystemSrand(Dart_NativeArguments arguments) {
-  Dart_EnterScope();
-  bool success = false;
-  Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0));
-  if (Dart_IsInteger(seed_object)) {
-    bool fits;
-    HandleError(Dart_IntegerFitsIntoInt64(seed_object, &fits));
-    if (fits) {
-      int64_t seed;
-      HandleError(Dart_IntegerToInt64(seed_object, &seed));
-      srand(static_cast<unsigned>(seed));
-      success = true;
-    }
-  }
-  SetBoolReturnValue(arguments, success);
-  Dart_ExitScope();
-}
-
-void GetDeviceScreenWidth(Dart_NativeArguments arguments) {
-  LOGI("GetDeviceScreenWidth");
-  Dart_EnterScope();
-  SetIntReturnValue(arguments, graphics->width());
-  Dart_ExitScope();
-}
-
-void GetDeviceScreenHeight(Dart_NativeArguments arguments) {
-  LOGI("GetDeviceScreenHeight");
-  Dart_EnterScope();
-  SetIntReturnValue(arguments, graphics->height());
-  Dart_ExitScope();
-}
-
-void SwapBuffers(Dart_NativeArguments arguments) {
-  LOGI("SwapBuffers");
-  Dart_EnterScope();
-  GLSwapBuffers();
-  CheckGLError("GLSwapBuffers");
-  Dart_ExitScope();
-}
-
-void GLAttachShader(Dart_NativeArguments arguments) {
-  LOGI("GLAttachShader");
-  Dart_EnterScope();
-
-  int64_t program = GetArgAsInt(arguments, 0);
-  int64_t shader = GetArgAsInt(arguments, 1);
-
-  glAttachShader(program, shader);
-  CheckGLError("glAttachShader");
-  Dart_ExitScope();
-}
-
-void GLBindBuffer(Dart_NativeArguments arguments) {
-  LOGI("GLBindBuffer");
-  Dart_EnterScope();
-
-  int64_t target = GetArgAsInt(arguments, 0);
-  int64_t buffer = GetArgAsInt(arguments, 1);
-
-  glBindBuffer(target, buffer);
-  CheckGLError("glBindBuffer");
-  Dart_ExitScope();
-}
-
-void GLBufferData(Dart_NativeArguments arguments) {
-  LOGI("GLBufferData");
-  Dart_EnterScope();
-
-  int64_t target = GetArgAsInt(arguments, 0);
-
-  Dart_Handle dataHandle = HandleError(Dart_GetNativeArgument(arguments, 1));
-  intptr_t size;
-  HandleError(Dart_ListLength(dataHandle, &size));
-
-  LOGI("Size: %d", static_cast<int>(size));
-
-  // TODO(vsm): No guarantee that this is a float!
-  float* data = new float[size];
-  for (int i = 0; i < size; i++) {
-    Dart_Handle elemHandle = HandleError(Dart_ListGetAt(dataHandle, i));
-    double value;
-    Dart_DoubleValue(elemHandle, &value);
-    data[i] = static_cast<float>(value);
-    LOGI("Value[%d]: %f", i, data[i]);
-  }
-
-  Dart_Handle usageHandle = HandleError(Dart_GetNativeArgument(arguments, 2));
-  int64_t usage;
-  HandleError(Dart_IntegerToInt64(usageHandle, &usage));
-
-  glBufferData(target, size * sizeof(data[0]), data, usage);
-  CheckGLError("glBufferData");
-  delete[] data;
-  Dart_ExitScope();
-}
-
-void GLCompileShader(Dart_NativeArguments arguments) {
-  LOGI("GLCompileShader");
-  Dart_EnterScope();
-  int64_t shader = GetArgAsInt(arguments, 0);
-  glCompileShader(shader);
-  CheckGLError("glCompileShader");
-  Dart_ExitScope();
-}
-
-void GLCreateBuffer(Dart_NativeArguments arguments) {
-  LOGI("GLCreateBuffer");
-  Dart_EnterScope();
-  GLuint buffer;
-  glGenBuffers(1, &buffer);
-  CheckGLError("glGenBuffers");
-  SetIntReturnValue(arguments, buffer);
-  Dart_ExitScope();
-}
-
-void GLCreateProgram(Dart_NativeArguments arguments) {
-  LOGI("GLCreateProgram");
-  Dart_EnterScope();
-  int64_t program = glCreateProgram();
-  CheckGLError("glCreateProgram");
-  SetIntReturnValue(arguments, program);
-  Dart_ExitScope();
-}
-
-void GLCreateShader(Dart_NativeArguments arguments) {
-  LOGI("GLCreateShader");
-  Dart_EnterScope();
-  int64_t type = GetArgAsInt(arguments, 0);
-  int64_t shader = glCreateShader((GLenum)type);
-  CheckGLError("glCreateShader");
-  SetIntReturnValue(arguments, shader);
-  Dart_ExitScope();
-}
-
-void GLDrawArrays(Dart_NativeArguments arguments) {
-  LOGI("GLDrawArrays");
-  Dart_EnterScope();
-
-  int64_t mode = GetArgAsInt(arguments, 0);
-  int64_t first = GetArgAsInt(arguments, 1);
-  int64_t count = GetArgAsInt(arguments, 2);
-
-  glDrawArrays(mode, first, count);
-