Version 0.2.9.0

svn merge -r 15867:16053 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@16054 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/.gitignore b/.gitignore
index 1a58486..41e6819 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@
 /ipch
 /out
 /xcodebuild
+/.flaky.log
 /*.Makefile
 /*.opensdf
 /*.pyc
diff --git a/compiler/java/com/google/dart/compiler/parser/DartParser.java b/compiler/java/com/google/dart/compiler/parser/DartParser.java
index f9f7700..129eb6a 100644
--- a/compiler/java/com/google/dart/compiler/parser/DartParser.java
+++ b/compiler/java/com/google/dart/compiler/parser/DartParser.java
@@ -2564,6 +2564,12 @@
           reportErrorAtPosition(prevPositionStart, prevPositionEnd,
                                 ParserErrorCode.SUPER_IS_NOT_VALID_AS_A_BOOLEAN_OPERAND);
         }
+        if (token == Token.EQ_STRICT) {
+          reportError(tokenOffset, ParserErrorCode.DEPRECATED_STRICT_EQ);
+        }
+        if (token == Token.NE_STRICT) {
+          reportError(tokenOffset, ParserErrorCode.DEPRECATED_STRICT_NE);
+        }
         DartExpression right;
         if (token == Token.IS) {
           beginTypeExpression();
@@ -3564,6 +3570,11 @@
       rollback();
       return null;
     }
+    if (function != null && function.getReturnTypeNode() != null) {
+      reportError(function.getReturnTypeNode(), ParserErrorCode.DEPRECATED_FUNCTION_LITERAL);
+    } else if (namePtr[0] != null) {
+      reportError(namePtr[0], ParserErrorCode.DEPRECATED_FUNCTION_LITERAL);
+    }
     return done(new DartFunctionExpression(namePtr[0], doneWithoutConsuming(function), false));
   }
 
diff --git a/compiler/java/com/google/dart/compiler/parser/ParserErrorCode.java b/compiler/java/com/google/dart/compiler/parser/ParserErrorCode.java
index 48f05f5..c035768 100644
--- a/compiler/java/com/google/dart/compiler/parser/ParserErrorCode.java
+++ b/compiler/java/com/google/dart/compiler/parser/ParserErrorCode.java
@@ -34,12 +34,15 @@
   DEPRECATED_CATCH("This style of catch clause has been deprecated. Please use the 'on' <type> " +
       "'catch' '(' <identifier> (',' <identifier>)? ')' form."),
   DEPRECATED_ABSTRACT_METHOD(ErrorSeverity.WARNING, "Modifier 'abstract' is deprecated for methods without body. Remove it."),
+  DEPRECATED_FUNCTION_LITERAL("Deprecated function literal syntax, remove return type and name"),
   DEPRECATED_GETTER("The presence of parentheses after the name of the getter "
       + "has been deprecated and will soon be disallowed. Please remove the parentheses."),
   DEPRECATED_INTERFACE("Deprecated declaration of the 'interface', use abstract 'class' instead"),
   DEPRECATED_USE_OF_FACTORY_KEYWORD("Deprecated use of the 'factory' keyword: use 'default' instead"),
   DEPRECATED_RAW_STRING("The use of '@' to prefix a raw string has been deprecated; use 'r' instead"),
   DEPRECATED_RESOURCE_DIRECTIVE("The #resource directive has been deprecated and will soon be disallowed"),
+  DEPRECATED_STRICT_EQ("Deprecated use of '===', use 'identical()' or '==' instead."),
+  DEPRECATED_STRICT_NE("Deprecated use of '!==', use '!identical()' or '!=' instead."),
   DEPRECATED_LIBRARY_DIRECTIVE("The '#library(url)' directive has been deprecated, use 'library name' instead"),
   DEPRECATED_IMPORT_DIRECTIVE("The '#import(url)' directive has been deprecated, use 'import url' instead"),
   DEPRECATED_SOURCE_DIRECTIVE("The '#source(url)' directive has been deprecated, use 'part url' instead"),
diff --git a/compiler/java/com/google/dart/compiler/resolver/Resolver.java b/compiler/java/com/google/dart/compiler/resolver/Resolver.java
index 588a000..89ed7f1 100644
--- a/compiler/java/com/google/dart/compiler/resolver/Resolver.java
+++ b/compiler/java/com/google/dart/compiler/resolver/Resolver.java
@@ -19,7 +19,6 @@
 import com.google.dart.compiler.ast.DartBlock;
 import com.google.dart.compiler.ast.DartBooleanLiteral;
 import com.google.dart.compiler.ast.DartBreakStatement;
-import com.google.dart.compiler.ast.DartCase;
 import com.google.dart.compiler.ast.DartCatchBlock;
 import com.google.dart.compiler.ast.DartClass;
 import com.google.dart.compiler.ast.DartComment;
@@ -768,7 +767,7 @@
                     break;
                 }
               } else {
-                targetConstructor = ((ClassElement) element).lookupConstructor(element.getName());
+                targetConstructor = ((ClassElement) element).lookupConstructor("");
               }
               Elements.setRedirectingFactoryConstructor(((ConstructorElement) member),
                   targetConstructor);
@@ -1132,21 +1131,6 @@
       return null;
     }
 
-    @Override
-    public Element visitCase(DartCase node) {
-      super.visitCase(node);
-      List<DartStatement> statements = node.getStatements();
-      // the last statement should be: break, continue, return, throw
-      if (!statements.isEmpty()) {
-        DartStatement lastStatement = statements.get(statements.size() - 1);
-        if (!isValidLastSwitchCaseStatement(lastStatement)) {
-          onError(lastStatement, ResolverErrorCode.SWITCH_CASE_FALL_THROUGH);
-        }
-      }
-      // done
-      return null;
-    }
-
     private boolean isValidLastSwitchCaseStatement(DartStatement statement) {
       if (statement instanceof DartExprStmt) {
         DartExprStmt exprStmt = (DartExprStmt) statement;
@@ -1160,9 +1144,23 @@
 
     @Override
     public Element visitSwitchMember(DartSwitchMember x) {
-      getContext().pushScope("<switch member>");
-      x.visitChildren(this);
-      getContext().popScope();
+      // visit children
+      {
+        getContext().pushScope("<switch member>");
+        x.visitChildren(this);
+        getContext().popScope();
+      }
+      // check fall-through
+      {
+        List<DartStatement> statements = x.getStatements();
+        // the last statement should be: break, continue, return, throw
+        if (!statements.isEmpty()) {
+          DartStatement lastStatement = statements.get(statements.size() - 1);
+          if (!isValidLastSwitchCaseStatement(lastStatement)) {
+            onError(lastStatement, ResolverErrorCode.SWITCH_CASE_FALL_THROUGH);
+          }
+        }
+      }
       return null;
     }
 
diff --git a/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java b/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java
index ebe4554..c2cefc9 100644
--- a/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java
+++ b/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java
@@ -24,7 +24,7 @@
   CANNOT_ASSIGN_TO_METHOD(ErrorSeverity.WARNING, "cannot assign value to method '%s'."),
   CANNOT_BE_RESOLVED("cannot resolve %s"),
   // TODO(zundel): error message needs JUnit test - how to test #imports in junit?
-  CANNOT_BE_RESOLVED_LIBRARY("cannot resolve %s in library %s"),
+  CANNOT_BE_RESOLVED_LIBRARY(ErrorSeverity.WARNING, "cannot resolve %s in library %s"),
   CANNOT_CALL_FUNCTION_TYPE_ALIAS("Function type aliases cannot be called"),
   // TODO(zundel): error message needs JUnit test - how to test #imports in junit?
   CANNOT_CALL_LIBRARY_PREFIX("Library prefixes cannot be called"),
diff --git a/compiler/java/com/google/dart/compiler/resolver/TypeErrorCode.java b/compiler/java/com/google/dart/compiler/resolver/TypeErrorCode.java
index 36c182d..0f360ac 100644
--- a/compiler/java/com/google/dart/compiler/resolver/TypeErrorCode.java
+++ b/compiler/java/com/google/dart/compiler/resolver/TypeErrorCode.java
@@ -62,6 +62,8 @@
   OPERATOR_WRONG_OPERAND_TYPE("operand of \"%s\" must be assignable to \"%s\", found \"%s\""),
   OVERRIDING_STATIC_MEMBER("overriding static member \"%s\" of \"%s\""),
   PLUS_CANNOT_BE_USED_FOR_STRING_CONCAT("'%s' cannot be used for string concatentation, use string interpolation or a StringBuffer instead"),
+  REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE(
+      "Target type of redirecting factory constructor '%s' is not subtype of '%s'"),
   SETTER_RETURN_TYPE("Specified return type of setter '%s' is non-void"),
   SETTER_TYPE_MUST_BE_ASSIGNABLE("Setter type '%s' must be assignable to getter type '%s'"),
   STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE(
diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
index e1790bf..1f2e102 100644
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
@@ -2096,7 +2096,7 @@
       DartTypeNode returnTypeNode = node.getFunction().getReturnTypeNode();
       if (modifiers.isFactory()
           && ElementKind.of(methodElement).equals(ElementKind.CONSTRUCTOR)) {
-        analyzeFactory(node.getName(), (ConstructorElement) methodElement);
+        analyzeFactory(node, node.getName(), (ConstructorElement) methodElement);
       } else if (modifiers.isSetter()) {
         if (returnTypeNode != null && returnTypeNode.getType() != voidType) {
           typeError(returnTypeNode, TypeErrorCode.SETTER_RETURN_TYPE, methodElement.getName());
@@ -2187,7 +2187,8 @@
       return superTypes;
     }
 
-    private void analyzeFactory(DartExpression name, final ConstructorElement methodElement) {
+    private void analyzeFactory(DartMethodDefinition node, DartExpression name,
+        final ConstructorElement methodElement) {
       ASTVisitor<Void> visitor = new ASTVisitor<Void>() {
         @Override
         public Void visitParameterizedTypeNode(DartParameterizedTypeNode node) {
@@ -2207,6 +2208,25 @@
         }
       };
       name.accept(visitor);
+      // redirecting factory constructor
+      if (methodElement instanceof ConstructorElement) {
+        ConstructorElement constructorElement = (ConstructorElement) methodElement;
+        ConstructorElement targetElement = constructorElement.getRedirectingFactoryConstructor();
+        if (targetElement != null) {
+          ClassElement targetEnclosingClass = (ClassElement) targetElement.getEnclosingElement();
+          Type sourceMethodType = methodElement.getType();
+          Type targetMethodType = targetElement.getType();
+          InterfaceType targetClassType = (InterfaceType) node.getRedirectedTypeName().getType();
+          targetMethodType = targetMethodType.subst(targetClassType.getArguments(),
+              targetEnclosingClass.getTypeParameters());
+          if (!types.isSubtype(targetMethodType, sourceMethodType)) {
+            DartNode errorNode = node.getRedirectedConstructorName() != null
+                ? node.getRedirectedConstructorName() : node.getRedirectedTypeName();
+            typeError(errorNode, TypeErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE,
+                targetMethodType, sourceMethodType);
+          }
+        }
+      }
     }
 
     @Override
diff --git a/compiler/java/com/google/dart/compiler/util/DartSourceString.java b/compiler/java/com/google/dart/compiler/util/DartSourceString.java
index 9bc3c0b..407d18b 100644
--- a/compiler/java/com/google/dart/compiler/util/DartSourceString.java
+++ b/compiler/java/com/google/dart/compiler/util/DartSourceString.java
@@ -79,7 +79,7 @@
   @Override
   public URI getUri() {
     try {
-      return new URI(null, null, getName(), null).normalize();
+      return new URI(null, null, getName(), null, null).normalize();
     } catch (URISyntaxException e) {
       throw new IllegalArgumentException(e);
     }
diff --git a/compiler/javatests/com/google/dart/compiler/parser/ClassesInterfaces.dart b/compiler/javatests/com/google/dart/compiler/parser/ClassesInterfaces.dart
index 9535c88..7faaeac 100644
--- a/compiler/javatests/com/google/dart/compiler/parser/ClassesInterfaces.dart
+++ b/compiler/javatests/com/google/dart/compiler/parser/ClassesInterfaces.dart
@@ -77,20 +77,12 @@
       id(x) { return x; }
       int id(x) { return x; }
       Box<int, double> id(x) { return x; }
-      var f = hest() { };
-      var f = int horse() { };
-      var f = Box<int> llama() { };
-      var f = Box<int, double> llama() { };
+      var f = () { };
       assert(x == 12);
-      id(void foo(x) {});
-      id(foo(x) {});
-      id(Box<int> foo(x) {});
-      id(Box<int, double> foo(x) {});
-      id(Box<int, double> foo);
+      id((x) {});
       a < b;
       int x = a < b;
       id(() {});
-      id(void _() {});
     }
   }
 
diff --git a/compiler/javatests/com/google/dart/compiler/parser/NegativeParserTest.java b/compiler/javatests/com/google/dart/compiler/parser/NegativeParserTest.java
index 65a57e1..e1c94ca 100644
--- a/compiler/javatests/com/google/dart/compiler/parser/NegativeParserTest.java
+++ b/compiler/javatests/com/google/dart/compiler/parser/NegativeParserTest.java
@@ -25,6 +25,24 @@
     parseExpectErrors("get foo() {}", errEx(ParserErrorCode.DEPRECATED_GETTER, 1, 5, 3));
   }
 
+  public void test_deprecatedStrictEQ() {
+    parseExpectErrors(makeCode(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "main() {",
+        "  1 === 2;",
+        "}",
+        ""), errEx(ParserErrorCode.DEPRECATED_STRICT_EQ, 3, 5, 3));
+  }
+
+  public void test_deprecatedStrictNE() {
+    parseExpectErrors(makeCode(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "main() {",
+        "  1 !== 2;",
+        "}",
+        ""), errEx(ParserErrorCode.DEPRECATED_STRICT_NE, 3, 5, 3));
+  }
+
   public void test_deprecatedAbstract() {
     parseExpectWarnings(makeCode(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -41,6 +59,19 @@
         errEx(ParserErrorCode.REDIRECTING_CONSTRUCTOR_ITSELF, 1, 30, 7));
   }
   
+  public void test_deprecatedFunctionLiteral() {
+    parseExpectWarnings(
+        makeCode(
+            "// filler filler filler filler filler filler filler filler filler filler",
+            "main() {",
+            "  var x = f() => 42;",
+            "  var y = int g() => 87;",
+            "}",
+            ""),
+        errEx(ParserErrorCode.DEPRECATED_FUNCTION_LITERAL, 3, 11, 1),
+        errEx(ParserErrorCode.DEPRECATED_FUNCTION_LITERAL, 4, 11, 3));
+  }
+  
   public void testFieldInitializerInRedirectionConstructor2() {
     parseExpectErrors(
         "class A { A(x) { } A.foo() : y = 5, this(5); var y; }",
@@ -515,28 +546,6 @@
         errEx(ParserErrorCode.NO_SPACE_AFTER_PLUS, 7, 9, 1));
   }
 
-  /**
-   * Separate test for invocation of function literal which has both return type and name.
-   */
-  public void test_invokeFunctionLiteral_returnType_name() {
-    DartParserRunner parserRunner =
-        parseExpectErrors(Joiner.on("\n").join(
-            "// filler filler filler filler filler filler filler filler filler filler",
-            "topLevelFunctionWithVeryLongNameToForceLineWrapping() {",
-            "  int f(p){}(0);", // invocation of function literal in statement, has type and name
-            "}",
-            ""));
-    assertEquals(
-        makeCode(
-            "// unit " + getName(),
-            "",
-            "topLevelFunctionWithVeryLongNameToForceLineWrapping() {",
-            "  int f(p) {",
-            "  }(0);",
-            "}"),
-        parserRunner.getDartUnit().toSource());
-  }
-
   public void test_formalParameters_const() throws Exception {
     parseExpectErrors(
         Joiner.on("\n").join(
@@ -558,7 +567,6 @@
             "  int f1(p){}", // declaration of function as statement, has type
             "  var res = (p){}(1);", // invocation of function literal in assignment
             "  (p){}(2);", // invocation of function literal in statement, no name
-            "  f2(p){}(3);", // invocation of function literal in statement, has name
             "  f3(p) => 4;", // function with => arrow ends with ';'
             "  (5);", // this is separate statement, not invocation of previous function
             "  join(promises, (p) => 6);", // function with => arrow as argument
@@ -578,8 +586,6 @@
             "  }(1);",
             "  (p) {",
             "  }(2);",
-            "  f2(p) {",
-            "  }(3);",
             "  f3(p) {",
             "    return 4;",
             "  };",
diff --git a/compiler/javatests/com/google/dart/compiler/parser/SyntaxTest.java b/compiler/javatests/com/google/dart/compiler/parser/SyntaxTest.java
index 2e908c1..5f90a79 100644
--- a/compiler/javatests/com/google/dart/compiler/parser/SyntaxTest.java
+++ b/compiler/javatests/com/google/dart/compiler/parser/SyntaxTest.java
@@ -1010,12 +1010,12 @@
             "      }",
             "    }",
             "    L: switch(1) {",
-            "     case 1: var result = f() { continue L; };", // bad
+            "     case 1: var result = () { continue L; };", // bad
             "    }",
             "  }",
             "}"),
             ParserErrorCode.CONTINUE_IN_CASE_MUST_HAVE_LABEL, 4, 23,
-            ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, 12, 42);
+            ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, 12, 41);
   }
 
   public void testRedundantAbruptlyTermainatedCaseStatement() throws Exception {
diff --git a/compiler/javatests/com/google/dart/compiler/resolver/CompileTimeConstantTest.java b/compiler/javatests/com/google/dart/compiler/resolver/CompileTimeConstantTest.java
index 5c270db..a86b588d 100644
--- a/compiler/javatests/com/google/dart/compiler/resolver/CompileTimeConstantTest.java
+++ b/compiler/javatests/com/google/dart/compiler/resolver/CompileTimeConstantTest.java
@@ -236,12 +236,6 @@
             errEx(ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION, 3, 26,2),
             errEx(ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION, 4, 19, 12));
   }
-
-  public void test_expressionsWithNull() {
-    resolveAndTestCtConst(Joiner.on("\n").join(
-        "class Object {}",
-        "var b = null === '';"));
-  }
   
   public void test_parameterDefaultValue_inLocalFunction() {
     resolveAndTestCtConstExpectErrors(
@@ -541,8 +535,6 @@
         " static const BOP7 = false || BOOL_LIT;",
         " static const BOP8 = STRING_LIT == 'World!';",
         " static const BOP9 = 'Hello' != STRING_LIT;",
-        " static const BOP10 = INT_LIT === INT_LIT_REF;",
-        " static const BOP11 = BOOL_LIT !== true;",
         "}"));
   }
 
@@ -625,32 +617,29 @@
   }
 
   public void testConstantBinaryExpression9() {
-    resolveAndTestCtConst(Joiner.on("\n").join(
-        "class Object {}",
-        "class bool {}",
-        "class int {}",
-        "class double {}",
-        "class num {}",
-        "class A {",
-        " static Object foo() { return true; }",
-        "}",
-        "class B {",
-        " const B();",
-        " static const OBJECT_LIT = const B();",
-        " static const INT_LIT = 1;",
-        " static const STRING_LIT = 'true';",
-        " static const BOP1 = STRING_LIT && true;",
-        " static const BOP2 = false || STRING_LIT;",
-        " static const BOP3 = 59 == OBJECT_LIT;",
-        " static const BOP4 = OBJECT_LIT != 59;",
-        " static const BOP5 = INT_LIT === OBJECT_LIT;",
-        " static const BOP6 = OBJECT_LIT !== true;",
-        "}"),
+    resolveAndTestCtConst(
+        Joiner.on("\n").join(
+            "class Object {}",
+            "class bool {}",
+            "class int {}",
+            "class double {}",
+            "class num {}",
+            "class A {",
+            " static Object foo() { return true; }",
+            "}",
+            "class B {",
+            " const B();",
+            " static const OBJECT_LIT = const B();",
+            " static const INT_LIT = 1;",
+            " static const STRING_LIT = 'true';",
+            " static const BOP1 = STRING_LIT && true;",
+            " static const BOP2 = false || STRING_LIT;",
+            " static const BOP3 = 59 == OBJECT_LIT;",
+            " static const BOP4 = OBJECT_LIT != 59;",
+            "}"),
         ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_BOOLEAN,
         ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_BOOLEAN,
         ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_STRING_NUMBER_BOOL,
-        ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_STRING_NUMBER_BOOL,
-        ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_STRING_NUMBER_BOOL,
         ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_STRING_NUMBER_BOOL);
   }
 
diff --git a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java
index dc76e65..bcad2fa 100644
--- a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java
+++ b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java
@@ -1162,8 +1162,8 @@
   public void testUndercoreInNamedParameterFunctionDefinition() {
     resolveAndTest(Joiner.on("\n").join(
         "class Object {}",
-        "var f = func({_foo}) {};"),
-        errEx(ResolverErrorCode.NAMED_PARAMETERS_CANNOT_START_WITH_UNDER, 2, 15, 4));
+        "func({_foo}) {}"),
+        errEx(ResolverErrorCode.NAMED_PARAMETERS_CANNOT_START_WITH_UNDER, 2, 7, 4));
   }
 
   public void testUndercoreInNamedParameterFunctionAlias() {
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
index 910e9d1..9f8cd3c 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
@@ -470,6 +470,8 @@
         "        throw new Exception();",
         "      case 4:",
         "        bar();",
+        "      default:",
+        "        bar();",
         "    }",
         "  }",
         "}",
@@ -477,7 +479,8 @@
         "");
     assertErrors(
         libraryResult.getErrors(),
-        errEx(ResolverErrorCode.SWITCH_CASE_FALL_THROUGH, 14, 9, 6));
+        errEx(ResolverErrorCode.SWITCH_CASE_FALL_THROUGH, 14, 9, 6),
+        errEx(ResolverErrorCode.SWITCH_CASE_FALL_THROUGH, 16, 9, 6));
   }
 
   /**
@@ -1146,14 +1149,19 @@
         "  assert('message');", // not 'bool'
         "  assert('null');", // not 'bool'
         "  assert(0);", // not 'bool'
-        "  assert(f() {});", // OK, dynamic
-        "  assert(bool f() {});", // OK, '() -> bool'
-        "  assert(Object f() {});", // OK, 'Object' compatible with 'bool'
-        "  assert(String f() {});", // not '() -> bool', return type
-        "  assert(bool f(x) {});", // not '() -> bool', parameter
+        "  assert(f1);", // OK, dynamic
+        "  assert(f2);", // OK, '() -> bool'
+        "  assert(f3);", // OK, 'Object' compatible with 'bool'
+        "  assert(f4);", // not '() -> bool', return type
+        "  assert(f5);", // not '() -> bool', parameter
         "  assert(true, false);", // not single argument
         "  assert;", // incomplete
         "}",
+        "f1() {}",
+        "bool f2() {}",
+        "Object f3() {}",
+        "String f4() {}",
+        "bool f5(x) {}",
         "");
     assertErrors(
         libraryResult.getErrors(),
@@ -1162,8 +1170,8 @@
         errEx(TypeErrorCode.ASSERT_BOOL, 5, 10, 9),
         errEx(TypeErrorCode.ASSERT_BOOL, 6, 10, 6),
         errEx(TypeErrorCode.ASSERT_BOOL, 7, 10, 1),
-        errEx(TypeErrorCode.ASSERT_BOOL, 11, 10, 13),
-        errEx(TypeErrorCode.ASSERT_BOOL, 12, 10, 12));
+        errEx(TypeErrorCode.ASSERT_BOOL, 11, 10, 2),
+        errEx(TypeErrorCode.ASSERT_BOOL, 12, 10, 2));
   }
 
   /**
@@ -3358,6 +3366,7 @@
         "  switch (true) {",
         "    default:",
         "      int v = foo;",
+        "      break;",
         "  }",
         "}",
         "");
@@ -3885,42 +3894,43 @@
   public void test_assignMethod() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
-        "class C {" +
+        "class C {",
         "  method() { }",
         "}",
         "main () {",
-        "  new C().method = _() {};",
-        "}");
-    assertErrors(
-        libraryResult.getErrors(),
-        errEx(TypeErrorCode.CANNOT_ASSIGN_TO, 5, 3, 14));
+        "  new C().method = f;",
+        "}",
+        "f() {}",
+        "");
+    assertErrors(libraryResult.getErrors(), errEx(TypeErrorCode.CANNOT_ASSIGN_TO, 6, 3, 14));
   }
 
   public void test_assignSetter() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
-        "class C {" +
+        "class C {",
         "  set method(arg) { }",
         "}",
         "main () {",
-        "  new C().method = _() {};",
-        "}");
-    assertErrors(
-        libraryResult.getErrors());
+        "  new C().method = f;",
+        "}",
+        "f() {}",
+        "");
+    assertErrors(libraryResult.getErrors());
   }
 
   public void test_assignGetter() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
-        "class C {" +
+        "class C {",
         "  get method { }",
         "}",
         "main () {",
-        "  new C().method = _() {};",
-        "}");
-    assertErrors(
-        libraryResult.getErrors(),
-        errEx(TypeErrorCode.FIELD_HAS_NO_SETTER, 5, 11, 6));
+        "  new C().method = f;",
+        "}",
+        "f() {}",
+        "");
+    assertErrors(libraryResult.getErrors(), errEx(TypeErrorCode.FIELD_HAS_NO_SETTER, 6, 11, 6));
   }
 
   /**
@@ -4590,7 +4600,7 @@
       assertNotNull(access.getElement());
     }
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=4315
@@ -4620,6 +4630,22 @@
   }
 
   /**
+   * Test that we already support cascaded calls in initializers. No implementation was changed.
+   * <p>
+   * http://code.google.com/p/dart/issues/detail?id=6955
+   */
+  public void test_cascade_inInitializer() throws Exception {
+    AnalyzeLibraryResult libraryResult = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class A {",
+        "  var f;",
+        "  A() : f = ''..length;",
+        "}",
+        "");
+    assertErrors(libraryResult.getErrors());
+  }
+
+  /**
    * Source is invalid, but should not cause {@link NullPointerException}.
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=4354
@@ -5041,7 +5067,7 @@
         errEx(ResolverErrorCode.REDIRECTION_CONSTRUCTOR_CYCLE, 6, 11, 7),
         errEx(ResolverErrorCode.REDIRECTION_CONSTRUCTOR_CYCLE, 9, 11, 7));
   }
-  
+
   public void test_redirectingFactoryConstructor_notConst_fromConst() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5058,6 +5084,78 @@
         errEx(ResolverErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_CONST, 7, 29, 5));
   }
 
+  public void test_redirectingFactoryConstructor_shouldBeSubType() throws Exception {
+    AnalyzeLibraryResult libraryResult = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class A {",
+        "  A() {}",
+        "  A.named(p0) {}",
+        "}",
+        "",
+        "class B {",
+        "  factory B.foo(p0) = A;",
+        "  factory B.bar() = A.named;",
+        "}",
+        "");
+    assertErrors(
+        libraryResult.getErrors(),
+        errEx(TypeErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE, 8, 23, 1),
+        errEx(TypeErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE, 9, 23, 5));
+  }
+
+  public void test_redirectingFactoryConstructor_shouldBeSubType2() throws Exception {
+    AnalyzeLibraryResult libraryResult = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class A<T> {",
+        "  A.named(T t) {}",
+        "}",
+        "",
+        "class B<T> {",
+        "  factory B.foo(T t) = A<T>.named;",
+        "}",
+        "class B2<T, V> {",
+        "  factory B2.foo(V v) = A<V>.named;",
+        "}",
+        "");
+    assertErrors(libraryResult.getErrors());
+  }
+  
+  public void test_redirectingFactoryConstructor_shouldBeSubType3() throws Exception {
+    AnalyzeLibraryResult libraryResult = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class A<T> {",
+        "  A(A<T> p) {}",
+        "}",
+        "",
+        "class B<T> {",
+        "  factory B.foo(A<T> p) = A;",
+        "}",
+        "");
+    assertErrors(libraryResult.getErrors());
+  }
+  
+  public void test_redirectingFactoryConstructor_notSubType_typeParameterBounds() throws Exception {
+    AnalyzeLibraryResult libraryResult = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class A1<T extends String> {",
+        "  A1() {}",
+        "}",
+        "class A2<T> {",
+        "  A2() {}",
+        "}",
+        "",
+        "class B {",
+        "  factory B.name1() = A1<String>;",
+        "  factory B.name2() = A1<int>;",
+        "  factory B.name3() = A2<String>;",
+        "  factory B.name4() = A2<int>;",
+        "}",
+        "");
+    assertErrors(
+        libraryResult.getErrors(),
+        errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 11, 26, 3));
+  }
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=4778
@@ -5831,11 +5929,11 @@
         "// filler filler filler filler filler filler filler filler filler filler",
         "class A {",
         "  var x;",
-        "  B() : x = (foo() { }) {}",
+        "  B() : x = 0 {}",
         "}",
         "");
     assertErrors(result.getErrors(),
-        errEx(ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR, 4, 9, 15));
+        errEx(ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR, 4, 9, 5));
   }
   
   public void test_variableReferencesItselfInInitializer() throws Exception {
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java
index 5889eb0..8f67edc 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java
@@ -123,9 +123,7 @@
     }
 
     EnumSet<Token> equalityOperators = EnumSet.of(Token.EQ,
-                                                  Token.NE,
-                                                  Token.EQ_STRICT,
-                                                  Token.NE_STRICT);
+                                                  Token.NE);
     for (Token op : equalityOperators) {
       String expression;
       expression = String.format("untyped %s untyped", op.getSyntax());
@@ -420,16 +418,9 @@
   }
 
   public void testFunctionObjectLiterals() {
-    analyze("{ bool b = foo() {}(); }");
-    analyze("{ int i = foo() {}(); }");
-    analyze("{ bool b = bool foo() { return null; }(); }");
-    analyze("{ int i = int foo() { return null; }(); }");
-    analyzeFail("{ int i = bool foo() { return null; }(); }",
-      TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
-    analyze("{ int i = Object _(Object x) { return x; }('fisk'); }");
-    analyzeFail("{ int i = String _(Object x) { return x; }(1); }",
-      TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
-    analyze("Function f = foo() {};");
+    analyze("{ bool b = () {}(); }");
+    analyze("{ int i = () {}(); }");
+    analyze("Function f = () {};");
   }
 
   public void testFunctionTypeAlias() {
@@ -475,8 +466,8 @@
 
     analyzeIn(foo, "voidFunction = stringFunction", 0);
     analyzeIn(foo, "stringFunction = intToStringFunction", 1);
-    analyzeIn(foo, "stringFunction = String foo() { return ''; }", 0);
-    analyzeIn(foo, "intToStringFunction = String foo() { return ''; }", 1);
+    analyzeIn(foo, "stringFunction = () { return ''; }", 0);
+    analyzeIn(foo, "intToStringFunction = () { return ''; }", 1);
   }
 
   public void testFunctionTypes() {
@@ -748,7 +739,7 @@
 
   public void testNamedFunctionTypeAlias() {
     loadFile("named_function_type_alias.dart");
-    analyze("VoidFunction f = foo() {};");
+    analyze("VoidFunction f = () {};");
   }
 
   public void testOddStuff() {
@@ -978,13 +969,13 @@
     analyzeIn(cls, "tField = ''", 1);
     analyzeIn(cls, "tField = true", 1);
 
-    analyzeIn(cls, "foo() { A a = null; T t = a; }()", 0);
-    analyzeIn(cls, "foo() { B b = null; T t = b; }()", 0);
-    analyzeIn(cls, "foo() { T t = null; A a = t; }()", 0);
-    analyzeIn(cls, "foo() { T t = null; B b = t; }()", 0);
-    analyzeIn(cls, "foo() { T t = 1; }()", 1);
-    analyzeIn(cls, "foo() { T t = ''; }()", 1);
-    analyzeIn(cls, "foo() { T t = true; }()", 1);
+    analyzeIn(cls, "() { A a = null; T t = a; }()", 0);
+    analyzeIn(cls, "() { B b = null; T t = b; }()", 0);
+    analyzeIn(cls, "() { T t = null; A a = t; }()", 0);
+    analyzeIn(cls, "() { T t = null; B b = t; }()", 0);
+    analyzeIn(cls, "() { T t = 1; }()", 1);
+    analyzeIn(cls, "() { T t = ''; }()", 1);
+    analyzeIn(cls, "() { T t = true; }()", 1);
   }
 
   public void testUnaryOperators() {
@@ -1085,11 +1076,11 @@
     checkAssignIn(element, "int", "intField('x')", 1);
     checkAssignIn(element, "String", "intField(2.2)", 1);
 
-    analyzeIn(element, "f(x) { x(); }", 0);
-    analyzeIn(element, "f(int x) { x(); }", 1);
-    analyzeIn(element, "f(int x()) { int i = x(); }", 0);
-    analyzeIn(element, "f(int x(String s)) { int i = x(1); }", 1);
-    analyzeIn(element, "f(int x(String s)) { int i = x(''); }", 0);
+    analyzeIn(element, "(x) { x(); }", 0);
+    analyzeIn(element, "(int x) { x(); }", 1);
+    analyzeIn(element, "(int x()) { int i = x(); }", 0);
+    analyzeIn(element, "(int x(String s)) { int i = x(1); }", 1);
+    analyzeIn(element, "(int x(String s)) { int i = x(''); }", 0);
   }
 
   public void testUnqualifiedGeneric() {
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTestCase.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTestCase.java
index e859745..ab903c7 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTestCase.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTestCase.java
@@ -211,7 +211,7 @@
   }
 
   private String assign(String type, String expression) {
-    return String.format("void foo() { %s x = %s; }", type, expression);
+    return String.format("() { %s x = %s; }", type, expression);
   }
 
   protected Type checkAssignIn(ClassElement element, String type, String expression, int errorCount) {
diff --git a/pkg/http/lib/src/base_request.dart b/pkg/http/lib/src/base_request.dart
index 4a8b5ce..eb36703 100644
--- a/pkg/http/lib/src/base_request.dart
+++ b/pkg/http/lib/src/base_request.dart
@@ -125,4 +125,6 @@
     if (!finalized) return;
     throw new StateError("Can't modify a finalized Request.");
   }
+
+  String toString() => "$method $url";
 }
diff --git a/pkg/http/test/request_test.dart b/pkg/http/test/request_test.dart
index e26ee75..1b3d4ca 100644
--- a/pkg/http/test/request_test.dart
+++ b/pkg/http/test/request_test.dart
@@ -387,5 +387,12 @@
       expect(request.finalize, throwsStateError);
     });
   });
+
+  group('#toString()', () {
+    test('includes the method and URL', () {
+      var request = new http.Request('POST', dummyUrl);
+      expect(request.toString(), 'POST $dummyUrl');
+    });
+  });
 }
 
diff --git a/pkg/http/test/utils.dart b/pkg/http/test/utils.dart
index 9e0d010..3548df0 100644
--- a/pkg/http/test/utils.dart
+++ b/pkg/http/test/utils.dart
@@ -29,7 +29,7 @@
       (request, response) {
     response.statusCode = 400;
     response.contentLength = 0;
-    closeResponse(request, response);
+    response.outputStream.close();
   });
 
   _server.addRequestHandler((request) => request.path == '/loop',
@@ -39,7 +39,7 @@
     response.headers.set('location',
         serverUrl.resolve('/loop?${n + 1}').toString());
     response.contentLength = 0;
-    closeResponse(request, response);
+    response.outputStream.close();
   });
 
   _server.addRequestHandler((request) => request.path == '/redirect',
@@ -47,7 +47,7 @@
     response.statusCode = 302;
     response.headers.set('location', serverUrl.resolve('/').toString());
     response.contentLength = 0;
-    closeResponse(request, response);
+    response.outputStream.close();
   });
 
   _server.defaultRequestHandler = (request, response) {
@@ -104,15 +104,6 @@
   _server = null;
 }
 
-/// Closes [response] while ignoring the body of [request].
-///
-/// Due to issue 6984, it's necessary to drain the request body before closing
-/// the response.
-void closeResponse(HttpRequest request, HttpResponse response) {
-  request.inputStream.onData = request.inputStream.read;
-  request.inputStream.onClosed = response.outputStream.close;
-}
-
 /// A matcher that matches JSON that parses to a value that matches the inner
 /// matcher.
 Matcher parse(matcher) => new _Parse(matcher);
diff --git a/pkg/intl/test/date_time_format_file_test_stub.dart b/pkg/intl/test/date_time_format_file_test_stub.dart
index 18b596c..6306bfb 100644
--- a/pkg/intl/test/date_time_format_file_test_stub.dart
+++ b/pkg/intl/test/date_time_format_file_test_stub.dart
@@ -6,7 +6,6 @@
  * Tests date formatting and parsing using locale data read from the
  * local file system.
  */
-
 library date_time_format_file_test;
 
 import '../lib/intl.dart';
@@ -25,11 +24,13 @@
 }
 
 void runEverything(Function getSubset) {
-  // Initialize all locales and wait for them to finish before running tests.
-  var futures = DateFormat.allLocalesWithSymbols().map(
+  // Initialize all locales sequentially before running tests. Be sure not
+  // to do it in parallel or we can run into ulimit problems on fast machines.
+  var futureList = Futures.forEach(DateFormat.allLocalesWithSymbols(),
       (locale) => initializeDateFormatting(locale, dataDirectory));
+
   test('Run all date formatting tests nested test', () {
-    Futures.wait(futures).then(
+    futureList.then(
         expectAsync1((results) => runDateTests(getSubset())));
   });
 }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index ca3ea25..a7383e2 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -34,9 +34,6 @@
 intl/test/find_default_locale_browser_test: Skip
 intl/test/date_time_format_http_request_test: Skip
 
-[ $runtime == vm && $system == windows ]
-http/test/http_test: Pass, Fail # http://dartbug.com/6967
-
 # Skip http request tests on Dartium while resolving an odd
 # error there that causes the tests to timeout.
 [ $runtime == dartium || $runtime == drt ]
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index ca6c601..4d8c9fa 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -9,50 +9,28 @@
 
 #include "bin/log.h"
 
-static int SetOsErrorMessage(char* os_error_message,
-                             int os_error_message_len) {
-  int error_code = GetLastError();
-  DWORD message_size =
-      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-                    NULL,
-                    error_code,
-                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                    os_error_message,
-                    os_error_message_len,
-                    NULL);
-  if (message_size == 0) {
-    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      Log::PrintErr("FormatMessage failed %d\n", GetLastError());
-    }
-    snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code);
-  }
-  os_error_message[os_error_message_len - 1] = '\0';
-  return error_code;
-}
-
-
 // Forward declaration.
-static bool ListRecursively(const char* dir_name,
+static bool ListRecursively(const wchar_t* dir_name,
                             bool recursive,
                             DirectoryListing* listing);
-static bool DeleteRecursively(const char* dir_name);
+static bool DeleteRecursively(const wchar_t* dir_name);
 
 
-static bool HandleDir(char* dir_name,
-                      char* path,
+static bool HandleDir(wchar_t* dir_name,
+                      wchar_t* path,
                       int path_length,
                       bool recursive,
                       DirectoryListing* listing) {
-  if (strcmp(dir_name, ".") != 0 &&
-      strcmp(dir_name, "..") != 0) {
-    size_t written = snprintf(path + path_length,
-                              MAX_PATH - path_length,
-                              "%s",
-                              dir_name);
-    if (written != strlen(dir_name)) {
+  if (wcscmp(dir_name, L".") != 0 &&
+      wcscmp(dir_name, L"..") != 0) {
+    size_t written = _snwprintf(path + path_length,
+                                MAX_PATH - path_length,
+                                L"%s",
+                                dir_name);
+    if (written != wcslen(dir_name)) {
       return false;
     }
-    char* utf8_path = StringUtils::SystemStringToUtf8(path);
+    char* utf8_path = StringUtils::WideToUtf8(path);
     bool ok = listing->HandleDirectory(utf8_path);
     free(utf8_path);
     if (!ok) return ok;
@@ -64,26 +42,26 @@
 }
 
 
-static bool HandleFile(char* file_name,
-                       char* path,
+static bool HandleFile(wchar_t* file_name,
+                       wchar_t* path,
                        int path_length,
                        DirectoryListing* listing) {
-  size_t written = snprintf(path + path_length,
-                            MAX_PATH - path_length,
-                            "%s",
-                            file_name);
-  if (written != strlen(file_name)) {
+  size_t written = _snwprintf(path + path_length,
+                              MAX_PATH - path_length,
+                              L"%s",
+                              file_name);
+  if (written != wcslen(file_name)) {
     return false;
   };
-  char* utf8_path = StringUtils::SystemStringToUtf8(path);
+  char* utf8_path = StringUtils::WideToUtf8(path);
   bool ok = listing->HandleFile(utf8_path);
   free(utf8_path);
   return ok;
 }
 
 
-static bool HandleEntry(LPWIN32_FIND_DATA find_file_data,
-                        char* path,
+static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data,
+                        wchar_t* path,
                         int path_length,
                         bool recursive,
                         DirectoryListing* listing) {
@@ -102,24 +80,24 @@
 
 // ComputeFullSearchPath must be called with a path array of size at
 // least MAX_PATH.
-static bool ComputeFullSearchPath(const char* dir_name,
-                                  char* path,
+static bool ComputeFullSearchPath(const wchar_t* dir_name,
+                                  wchar_t* path,
                                   int* path_length) {
   // GetFullPathName only works in a multi-threaded environment if
   // SetCurrentDirectory is not used. We currently have no plan for
   // exposing SetCurrentDirectory.
-  size_t written = GetFullPathName(dir_name, MAX_PATH, path, NULL);
+  size_t written = GetFullPathNameW(dir_name, MAX_PATH, path, NULL);
   // GetFullPathName only accepts input strings of size less than
   // MAX_PATH and returns 0 to indicate failure for paths longer than
   // that. Therefore the path buffer is always big enough.
-  if (written == 0) {
+  if (written == 0 || written > MAX_PATH) {
     return false;
   }
   *path_length = written;
-  written = snprintf(path + *path_length,
-                     MAX_PATH - *path_length,
-                     "%s",
-                     "\\*");
+  written = _snwprintf(path + *path_length,
+                       MAX_PATH - *path_length,
+                       L"%s",
+                       L"\\*");
   if (written != 2) {
     return false;
   }
@@ -128,14 +106,14 @@
 }
 
 static void PostError(DirectoryListing* listing,
-                      const char* dir_name) {
-  const char* utf8_path = StringUtils::SystemStringToUtf8(dir_name);
+                      const wchar_t* dir_name) {
+  const char* utf8_path = StringUtils::WideToUtf8(dir_name);
   listing->HandleError(utf8_path);
   free(const_cast<char*>(utf8_path));
 }
 
 
-static bool ListRecursively(const char* dir_name,
+static bool ListRecursively(const wchar_t* dir_name,
                             bool recursive,
                             DirectoryListing* listing) {
   // Compute full path for the directory currently being listed.  The
@@ -143,7 +121,7 @@
   // recursive traversal. path_length does not always equal
   // strlen(path) but indicates the current prefix of path that is the
   // path of the current directory in the traversal.
-  char* path = static_cast<char*>(malloc(MAX_PATH));
+  wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t)));
   int path_length = 0;
   bool valid = ComputeFullSearchPath(dir_name, path, &path_length);
   if (!valid) {
@@ -152,8 +130,8 @@
     return false;
   }
 
-  WIN32_FIND_DATA find_file_data;
-  HANDLE find_handle = FindFirstFile(path, &find_file_data);
+  WIN32_FIND_DATAW find_file_data;
+  HANDLE find_handle = FindFirstFileW(path, &find_file_data);
 
   // Adjust the path by removing the '*' used for the search.
   path_length -= 1;
@@ -171,7 +149,7 @@
                              recursive,
                              listing);
 
-  while ((FindNextFile(find_handle, &find_file_data) != 0)) {
+  while ((FindNextFileW(find_handle, &find_file_data) != 0)) {
     success = HandleEntry(&find_file_data,
                           path,
                           path_length,
@@ -194,18 +172,18 @@
 }
 
 
-static bool DeleteFile(char* file_name,
-                       char* path,
+static bool DeleteFile(wchar_t* file_name,
+                       wchar_t* path,
                        int path_length) {
-  size_t written = snprintf(path + path_length,
-                            MAX_PATH - path_length,
-                            "%s",
-                            file_name);
-  if (written != strlen(file_name)) {
+  size_t written = _snwprintf(path + path_length,
+                              MAX_PATH - path_length,
+                              L"%s",
+                              file_name);
+  if (written != wcslen(file_name)) {
     return false;
   }
 
-  if (DeleteFile(path) != 0) {
+  if (DeleteFileW(path) != 0) {
     return true;
   }
 
@@ -213,7 +191,7 @@
   // again. This mirrors Linux/Mac where a directory containing read-only files
   // can still be recursively deleted.
   if (GetLastError() == ERROR_ACCESS_DENIED) {
-    DWORD attributes = GetFileAttributes(path);
+    DWORD attributes = GetFileAttributesW(path);
     if (attributes == INVALID_FILE_ATTRIBUTES) {
       return false;
     }
@@ -221,11 +199,11 @@
     if ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
       attributes &= ~FILE_ATTRIBUTE_READONLY;
 
-      if (SetFileAttributes(path, attributes) == 0) {
+      if (SetFileAttributesW(path, attributes) == 0) {
         return false;
       }
 
-      return DeleteFile(path) != 0;
+      return DeleteFileW(path) != 0;
     }
   }
 
@@ -233,16 +211,16 @@
 }
 
 
-static bool DeleteDir(char* dir_name,
-                      char* path,
+static bool DeleteDir(wchar_t* dir_name,
+                      wchar_t* path,
                       int path_length) {
-  if (strcmp(dir_name, ".") != 0 &&
-      strcmp(dir_name, "..") != 0) {
-    size_t written = snprintf(path + path_length,
-                              MAX_PATH - path_length,
-                              "%s",
-                              dir_name);
-    if (written != strlen(dir_name)) {
+  if (wcscmp(dir_name, L".") != 0 &&
+      wcscmp(dir_name, L"..") != 0) {
+    size_t written = _snwprintf(path + path_length,
+                                MAX_PATH - path_length,
+                                L"%s",
+                                dir_name);
+    if (written != wcslen(dir_name)) {
       return false;
     }
     return DeleteRecursively(path);
@@ -251,8 +229,8 @@
 }
 
 
-static bool DeleteEntry(LPWIN32_FIND_DATA find_file_data,
-                        char* path,
+static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data,
+                        wchar_t* path,
                         int path_length) {
   DWORD attributes = find_file_data->dwFileAttributes;
 
@@ -264,14 +242,14 @@
 }
 
 
-static bool DeleteRecursively(const char* dir_name) {
+static bool DeleteRecursively(const wchar_t* dir_name) {
   // If the directory is a junction, it's pointing to some other place in the
   // filesystem that we do not want to recurse into.
-  DWORD attributes = GetFileAttributes(dir_name);
+  DWORD attributes = GetFileAttributesW(dir_name);
   if ((attributes != INVALID_FILE_ATTRIBUTES) &&
       (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
     // Just delete the junction itself.
-    return RemoveDirectory(dir_name) != 0;
+    return RemoveDirectoryW(dir_name) != 0;
   }
 
   // Compute full path for the directory currently being deleted.  The
@@ -279,7 +257,7 @@
   // recursive traversal. path_length does not always equal
   // strlen(path) but indicates the current prefix of path that is the
   // path of the current directory in the traversal.
-  char* path = static_cast<char*>(malloc(MAX_PATH));
+  wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t)));
   int path_length = 0;
   bool valid = ComputeFullSearchPath(dir_name, path, &path_length);
   if (!valid) {
@@ -287,8 +265,8 @@
     return false;
   }
 
-  WIN32_FIND_DATA find_file_data;
-  HANDLE find_handle = FindFirstFile(path, &find_file_data);
+  WIN32_FIND_DATAW find_file_data;
+  HANDLE find_handle = FindFirstFileW(path, &find_file_data);
 
   // Adjust the path by removing the '*' used for the search.
   path_length -= 1;
@@ -301,7 +279,7 @@
 
   bool success = DeleteEntry(&find_file_data, path, path_length);
 
-  while ((FindNextFile(find_handle, &find_file_data) != 0) && success) {
+  while ((FindNextFileW(find_handle, &find_file_data) != 0) && success) {
     success = success && DeleteEntry(&find_file_data, path, path_length);
   }
 
@@ -309,7 +287,7 @@
 
   if ((GetLastError() != ERROR_NO_MORE_FILES) ||
       (FindClose(find_handle) == 0) ||
-      (RemoveDirectory(dir_name) == 0)) {
+      (RemoveDirectoryW(dir_name) == 0)) {
     return false;
   }
 
@@ -320,15 +298,15 @@
 bool Directory::List(const char* dir_name,
                      bool recursive,
                      DirectoryListing* listing) {
-  const char* system_name = StringUtils::Utf8ToSystemString(dir_name);
+  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
   bool completed = ListRecursively(system_name, recursive, listing);
-  free(const_cast<char*>(system_name));
+  free(const_cast<wchar_t*>(system_name));
   return completed;
 }
 
 
-static Directory::ExistsResult ExistsHelper(const char* dir_name) {
-  DWORD attributes = GetFileAttributes(dir_name);
+static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) {
+  DWORD attributes = GetFileAttributesW(dir_name);
   if (attributes == INVALID_FILE_ATTRIBUTES) {
     DWORD last_error = GetLastError();
     if (last_error == ERROR_FILE_NOT_FOUND ||
@@ -347,33 +325,33 @@
 
 
 Directory::ExistsResult Directory::Exists(const char* dir_name) {
-  const char* system_name = StringUtils::Utf8ToSystemString(dir_name);
+  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
   Directory::ExistsResult result = ExistsHelper(system_name);
-  free(const_cast<char*>(system_name));
+  free(const_cast<wchar_t*>(system_name));
   return result;
 }
 
 
 char* Directory::Current() {
-  int length = GetCurrentDirectory(0, NULL);
-  char* current = reinterpret_cast<char*>(malloc(length + 1));
-  GetCurrentDirectory(length + 1, current);
-  char* result = StringUtils::SystemStringToUtf8(current);
-  free(current);
+  int length = GetCurrentDirectoryW(0, NULL);
+  wchar_t* current = new wchar_t[length + 1];
+  GetCurrentDirectoryW(length + 1, current);
+  char* result = StringUtils::WideToUtf8(current);
+  delete[] current;
   return result;
 }
 
 
 bool Directory::Create(const char* dir_name) {
-  const char* system_name = StringUtils::Utf8ToSystemString(dir_name);
+  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
   // If the directory already exists and is a directory do not
   // attempt to create it again and treat it as a success.
   if (ExistsHelper(system_name) == EXISTS) {
-    free(const_cast<char*>(system_name));
+    free(const_cast<wchar_t*>(system_name));
     return true;
   }
-  int create_status = CreateDirectory(system_name, NULL);
-  free(const_cast<char*>(system_name));
+  int create_status = CreateDirectoryW(system_name, NULL);
+  free(const_cast<wchar_t*>(system_name));
   return (create_status != 0);
 }
 
@@ -383,30 +361,29 @@
   // dir_template.  Creates this directory, with a default security
   // descriptor inherited from its parent directory.
   // The return value must be freed by the caller.
-  char* path = static_cast<char*>(malloc(MAX_PATH));
+  wchar_t* path = static_cast<wchar_t*>(malloc(MAX_PATH * sizeof(wchar_t)));
   int path_length;
   if (0 == strncmp(const_template, "", 1)) {
-    path_length = GetTempPath(MAX_PATH, path);
+    path_length = GetTempPathW(MAX_PATH, path);
     if (path_length == 0) {
       free(path);
       return NULL;
     }
   } else {
-    const char* system_template =
-        StringUtils::Utf8ToSystemString(const_template);
-    snprintf(path, MAX_PATH, "%s", system_template);
-    free(const_cast<char*>(system_template));
-    path_length = strlen(path);
+    const wchar_t* system_template = StringUtils::Utf8ToWide(const_template);
+    _snwprintf(path, MAX_PATH, L"%s", system_template);
+    free(const_cast<wchar_t*>(system_template));
+    path_length = wcslen(path);
   }
   // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44.
   if (path_length > MAX_PATH - 44) {
     free(path);
     return NULL;
   }
-  if ((path)[path_length - 1] == '\\') {
+  if ((path)[path_length - 1] == L'\\') {
     // No base name for the directory - use "tempdir".
-    snprintf(path + path_length, MAX_PATH - path_length, "tempdir");
-    path_length = strlen(path);
+    _snwprintf(path + path_length, MAX_PATH - path_length, L"tempdir");
+    path_length = wcslen(path);
   }
 
   UUID uuid;
@@ -415,19 +392,20 @@
     free(path);
     return NULL;
   }
-  RPC_CSTR uuid_string;
-  status = UuidToString(&uuid, &uuid_string);
+  RPC_WSTR uuid_string;
+  status = UuidToStringW(&uuid, &uuid_string);
   if (status != RPC_S_OK) {
     free(path);
     return NULL;
   }
 
-  snprintf(path + path_length, MAX_PATH - path_length, "-%s", uuid_string);
-  if (!CreateDirectory(path, NULL)) {
+  _snwprintf(path + path_length, MAX_PATH - path_length, L"-%s", uuid_string);
+  RpcStringFreeW(&uuid_string);
+  if (!CreateDirectoryW(path, NULL)) {
     free(path);
     return NULL;
   }
-  char* result = StringUtils::SystemStringToUtf8(path);
+  char* result = StringUtils::WideToUtf8(path);
   free(path);
   return result;
 }
@@ -435,22 +413,20 @@
 
 bool Directory::Delete(const char* dir_name, bool recursive) {
   bool result = false;
-  const char* system_dir_name =
-      StringUtils::Utf8ToSystemString(dir_name);
+  const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name);
   if (!recursive) {
-    result = (RemoveDirectory(system_dir_name) != 0);
+    result = (RemoveDirectoryW(system_dir_name) != 0);
   } else {
     result = DeleteRecursively(system_dir_name);
   }
-  free(const_cast<char*>(system_dir_name));
+  free(const_cast<wchar_t*>(system_dir_name));
   return result;
 }
 
 
 bool Directory::Rename(const char* path, const char* new_path) {
-  const char* system_path = StringUtils::Utf8ToSystemString(path);
-  const char* system_new_path =
-      StringUtils::Utf8ToSystemString(new_path);
+  const wchar_t* system_path = StringUtils::Utf8ToWide(path);
+  const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
   ExistsResult exists = ExistsHelper(system_path);
   if (exists != EXISTS) return false;
   ExistsResult new_exists = ExistsHelper(system_new_path);
@@ -463,8 +439,8 @@
   }
   DWORD flags = MOVEFILE_WRITE_THROUGH;
   int move_status =
-      MoveFileEx(system_path, system_new_path, flags);
-  free(const_cast<char*>(system_path));
-  free(const_cast<char*>(system_new_path));
+      MoveFileExW(system_path, system_new_path, flags);
+  free(const_cast<wchar_t*>(system_path));
+  free(const_cast<wchar_t*>(system_new_path));
   return (move_status != 0);
 }
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index a9cef38..9f6bae8c 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -105,9 +105,9 @@
   if ((mode & kTruncate) != 0) {
     flags = flags | O_TRUNC;
   }
-  const char* system_name = StringUtils::Utf8ToSystemString(name);
-  int fd = open(system_name, flags, 0666);
-  free(const_cast<char*>(system_name));
+  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  int fd = _wopen(system_name, flags, 0666);
+  free(const_cast<wchar_t*>(system_name));
   if (fd < 0) {
     return NULL;
   }
@@ -128,10 +128,10 @@
 
 
 bool File::Exists(const char* name) {
-  struct stat st;
-  const char* system_name = StringUtils::Utf8ToSystemString(name);
-  bool stat_status = stat(system_name, &st);
-  free(const_cast<char*>(system_name));
+  struct _stat st;
+  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  bool stat_status = _wstat(system_name, &st);
+  free(const_cast<wchar_t*>(system_name));
   if (stat_status == 0) {
     return ((st.st_mode & S_IFMT) == S_IFREG);
   } else {
@@ -141,9 +141,9 @@
 
 
 bool File::Create(const char* name) {
-  const char* system_name = StringUtils::Utf8ToSystemString(name);
-  int fd = open(system_name, O_RDONLY | O_CREAT, 0666);
-  free(const_cast<char*>(system_name));
+  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666);
+  free(const_cast<wchar_t*>(system_name));
   if (fd < 0) {
     return false;
   }
@@ -152,9 +152,9 @@
 
 
 bool File::Delete(const char* name) {
-  const char* system_name = StringUtils::Utf8ToSystemString(name);
-  int status = remove(system_name);
-  free(const_cast<char*>(system_name));
+  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  int status = _wremove(system_name);
+  free(const_cast<wchar_t*>(system_name));
   if (status == -1) {
     return false;
   }
@@ -163,10 +163,10 @@
 
 
 off_t File::LengthFromName(const char* name) {
-  struct stat st;
-  const char* system_name = StringUtils::Utf8ToSystemString(name);
-  int stat_status = stat(system_name, &st);
-  free(const_cast<char*>(system_name));
+  struct _stat st;
+  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  int stat_status = _wstat(system_name, &st);
+  free(const_cast<wchar_t*>(system_name));
   if (stat_status == 0) {
     return st.st_size;
   }
@@ -175,10 +175,10 @@
 
 
 time_t File::LastModified(const char* name) {
-  struct stat st;
-  const char* system_name = StringUtils::Utf8ToSystemString(name);
-  int stat_status = stat(system_name, &st);
-  free(const_cast<char*>(system_name));
+  struct _stat st;
+  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  int stat_status = _wstat(system_name, &st);
+  free(const_cast<wchar_t*>(system_name));
   if (stat_status == 0) {
     return st.st_mtime;
   }
@@ -196,29 +196,30 @@
 
 
 char* File::GetCanonicalPath(const char* pathname) {
-  struct stat st;
-  const char* system_name = StringUtils::Utf8ToSystemString(pathname);
-  int stat_status = stat(system_name, &st);
+  struct _stat st;
+  const wchar_t* system_name = StringUtils::Utf8ToWide(pathname);
+  int stat_status = _wstat(system_name, &st);
   if (stat_status != 0) {
     SetLastError(ERROR_FILE_NOT_FOUND);
-    free(const_cast<char*>(system_name));
+    free(const_cast<wchar_t*>(system_name));
     return NULL;
   }
-  int required_size = GetFullPathName(system_name, 0, NULL, NULL);
-  char* path = static_cast<char*>(malloc(required_size));
-  int written = GetFullPathName(system_name, required_size, path, NULL);
-  free(const_cast<char*>(system_name));
+  int required_size = GetFullPathNameW(system_name, 0, NULL, NULL);
+  wchar_t* path =
+      static_cast<wchar_t*>(malloc(required_size * sizeof(wchar_t)));
+  int written = GetFullPathNameW(system_name, required_size, path, NULL);
+  free(const_cast<wchar_t*>(system_name));
   ASSERT(written == (required_size - 1));
-  char* result = StringUtils::SystemStringToUtf8(path);
+  char* result = StringUtils::WideToUtf8(path);
   free(path);
   return result;
 }
 
 
 char* File::GetContainingDirectory(char* pathname) {
-  struct stat st;
-  char* system_name = StringUtils::Utf8ToSystemString(pathname);
-  int stat_status = stat(system_name, &st);
+  struct _stat st;
+  wchar_t* system_name = StringUtils::Utf8ToWide(pathname);
+  int stat_status = _wstat(system_name, &st);
   if (stat_status == 0) {
     if ((st.st_mode & S_IFMT) != S_IFREG) {
       SetLastError(ERROR_FILE_NOT_FOUND);
@@ -230,29 +231,32 @@
     free(system_name);
     return NULL;
   }
-  int required_size = GetFullPathName(system_name, 0, NULL, NULL);
-  char* path = static_cast<char*>(malloc(required_size));
-  char* file_part = NULL;
+  int required_size = GetFullPathNameW(system_name, 0, NULL, NULL);
+  wchar_t* path =
+      static_cast<wchar_t*>(malloc(required_size * sizeof(wchar_t)));
+  wchar_t* file_part = NULL;
   int written =
-    GetFullPathName(system_name, required_size, path, &file_part);
+    GetFullPathNameW(system_name, required_size, path, &file_part);
   free(system_name);
   ASSERT(written == (required_size - 1));
   ASSERT(file_part != NULL);
   ASSERT(file_part > path);
-  ASSERT(file_part[-1] == '\\');
+  ASSERT(file_part[-1] == L'\\');
   file_part[-1] = '\0';
-  char* result = StringUtils::SystemStringToUtf8(path);
+  char* result = StringUtils::WideToUtf8(path);
   free(path);
   return result;
 }
 
 
 const char* File::PathSeparator() {
+  // This is already UTF-8 encoded.
   return "\\";
 }
 
 
 const char* File::StringEscapedPathSeparator() {
+  // This is already UTF-8 encoded.
   return "\\\\";
 }
 
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 9c8ebb3..750fde4 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -40,10 +40,11 @@
   V(Socket_GetError, 1)                                                        \
   V(Socket_GetStdioHandle, 2)                                                  \
   V(Socket_NewServicePort, 0)                                                  \
-  V(SecureSocket_Connect, 5)                                                   \
+  V(SecureSocket_Connect, 8)                                                   \
   V(SecureSocket_Destroy, 1)                                                   \
   V(SecureSocket_Handshake, 1)                                                 \
   V(SecureSocket_Init, 1)                                                      \
+  V(SecureSocket_PeerCertificate, 1)                                           \
   V(SecureSocket_ProcessBuffer, 2)                                             \
   V(SecureSocket_RegisterBadCertificateCallback, 2)                            \
   V(SecureSocket_RegisterHandshakeCompleteCallback, 2)                         \
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 8700364..63d00dc 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -257,7 +257,7 @@
   bool result = false;
   for (int i = 0; i < argc; i++) {
     char* arg = argv[i];
-    argv[i] = StringUtils::SystemStringToUtf8(arg);
+    argv[i] = StringUtils::ConsoleStringToUtf8(arg);
     if (i == 0) {
       result = argv[i] != arg;
     } else {
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index 38cafbe..9ee2172 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -20,10 +20,6 @@
   // deallocated by the caller.
   static const char* OperatingSystem();
 
-  // Returns a string representation of an error code. The returned
-  // string must be deallocated by the caller.
-  static char* StrError(int error_code);
-
   // Extracts the local hostname.
   static bool LocalHostname(char* buffer, intptr_t buffer_length);
 
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 206eca3..a05de34 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -65,12 +65,3 @@
 void Platform::FreeEnvironment(char** env, intptr_t count) {
   delete[] env;
 }
-
-
-char* Platform::StrError(int error_code) {
-  static const int kBufferSize = 1024;
-  char* error = static_cast<char*>(malloc(kBufferSize));
-  error[0] = '\0';
-  strerror_r(error_code, error, kBufferSize);
-  return error;
-}
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index 2d77576..da91bc5 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -65,16 +65,3 @@
 void Platform::FreeEnvironment(char** env, intptr_t count) {
   delete[] env;
 }
-
-
-char* Platform::StrError(int error_code) {
-  static const int kBufferSize = 1024;
-  char* error = static_cast<char*>(malloc(kBufferSize));
-  error[0] = '\0';
-  char* error_str = strerror_r(error_code, error, kBufferSize);
-  if (error_str != error) {
-    size_t written = snprintf(error, kBufferSize, "%s", error_str);
-    ASSERT(written == strlen(error_str));
-  }
-  return error;
-}
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 822399d..87e8c6f 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -70,12 +70,3 @@
 void Platform::FreeEnvironment(char** env, intptr_t count) {
   delete[] env;
 }
-
-
-char* Platform::StrError(int error_code) {
-  static const int kBufferSize = 1024;
-  char* error = static_cast<char*>(malloc(kBufferSize));
-  error[0] = '\0';
-  strerror_r(error_code, error, kBufferSize);
-  return error;
-}
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 750caa6..090fcf2 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -36,56 +36,27 @@
 
 
 char** Platform::Environment(intptr_t* count) {
-  char* strings = GetEnvironmentStrings();
+  wchar_t* strings = GetEnvironmentStringsW();
   if (strings == NULL) return NULL;
-  char* tmp = strings;
+  wchar_t* tmp = strings;
   intptr_t i = 0;
   while (*tmp != '\0') {
     i++;
-    tmp += (strlen(tmp) + 1);
+    tmp += (wcslen(tmp) + 1);
   }
   *count = i;
   char** result = new char*[i];
   tmp = strings;
   for (intptr_t current = 0; current < i; current++) {
-    result[current] = StringUtils::SystemStringToUtf8(tmp);
-    tmp += (strlen(tmp) + 1);
+    result[current] = StringUtils::WideToUtf8(tmp);
+    tmp += (wcslen(tmp) + 1);
   }
-  FreeEnvironmentStrings(strings);
+  FreeEnvironmentStringsW(strings);
   return result;
 }
 
+
 void Platform::FreeEnvironment(char** env, int count) {
   for (int i = 0; i < count; i++) free(env[i]);
   delete[] env;
 }
-
-
-char* Platform::StrError(int error_code) {
-  static const int kBufferSize = 1024;
-  char* error = static_cast<char*>(malloc(kBufferSize));
-  DWORD message_size =
-      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-                    NULL,
-                    error_code,
-                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                    error,
-                    kBufferSize,
-                    NULL);
-  if (message_size == 0) {
-    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      Log::PrintErr("FormatMessage failed %d\n", GetLastError());
-    }
-    snprintf(error, kBufferSize, "OS Error %d", error_code);
-  }
-  // Strip out \r\n at the end of the generated message and ensure
-  // null termination.
-  if (message_size > 2 &&
-      error[message_size - 2] == '\r' &&
-      error[message_size - 1] == '\n') {
-    error[message_size - 2] = '\0';
-  } else {
-    error[kBufferSize - 1] = '\0';
-  }
-  return error;
-}
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index e513939..740e4a4 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -122,8 +122,7 @@
   Dart_Handle err_handle = Dart_GetNativeArgument(args, 7);
   Dart_Handle exit_handle = Dart_GetNativeArgument(args, 8);
   intptr_t pid = -1;
-  static const int kMaxChildOsErrorMessageLength = 256;
-  char os_error_message[kMaxChildOsErrorMessageLength];
+  char* os_error_message = NULL;
 
   int error_code = Process::Start(path,
                                   string_args,
@@ -136,7 +135,7 @@
                                   &err,
                                   &pid,
                                   &exit_event,
-      os_error_message, kMaxChildOsErrorMessageLength);
+                                  &os_error_message);
   if (error_code == 0) {
     Socket::SetSocketIdNativeField(in_handle, in);
     Socket::SetSocketIdNativeField(out_handle, out);
@@ -151,6 +150,7 @@
   }
   delete[] string_args;
   delete[] string_environment;
+  free(os_error_message);
   Dart_SetReturnValue(args, Dart_NewBoolean(error_code == 0));
   Dart_ExitScope();
 }
@@ -194,7 +194,7 @@
     Dart_PropagateError(result);
   }
   char* str =
-      StringUtils::SystemStringToUtf8(reinterpret_cast<char*>(buffer));
+      StringUtils::ConsoleStringToUtf8(reinterpret_cast<char*>(buffer));
   Dart_SetReturnValue(args, DartUtils::NewString(str));
   if (str != reinterpret_cast<char*>(buffer)) free(str);
   Dart_ExitScope();
@@ -205,7 +205,7 @@
   Dart_EnterScope();
   Dart_Handle str = Dart_GetNativeArgument(args, 0);
   const char* utf8 = DartUtils::GetStringValue(str);
-  const char* system_string = StringUtils::Utf8ToSystemString(utf8);
+  const char* system_string = StringUtils::Utf8ToConsoleString(utf8);
   int external_length = strlen(system_string);
   uint8_t* buffer = NULL;
   Dart_Handle external_array = IOBuffer::Allocate(external_length, &buffer);
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index f3ef5d8..0d3f704 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -24,8 +24,7 @@
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_handler,
-                   char* os_error_message,
-                   int os_error_message_len);
+                   char** os_error_message);
 
   // Kill a process with a given pid.
   static bool Kill(intptr_t id, int signal);
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 3d593e2..d18c92b 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -258,16 +258,8 @@
 dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
 
 
-static char* SafeStrNCpy(char* dest, const char* src, size_t n) {
-  strncpy(dest, src, n);
-  dest[n - 1] = '\0';
-  return dest;
-}
-
-
-static void SetChildOsErrorMessage(char* os_error_message,
-                                   int os_error_message_len) {
-  SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len);
+static void SetChildOsErrorMessage(char** os_error_message) {
+  *os_error_message = strdup(strerror(errno));
 }
 
 
@@ -315,8 +307,7 @@
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_event,
-                   char* os_error_message,
-                   int os_error_message_len) {
+                   char** os_error_message) {
   pid_t pid;
   int read_in[2];  // Pipe for stdout to child process.
   int read_err[2];  // Pipe for stderr to child process.
@@ -326,49 +317,49 @@
 
   bool initialized = ExitCodeHandler::EnsureInitialized();
   if (!initialized) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     Log::PrintErr("Error initializing exit code handler: %s\n",
-                 os_error_message);
+                 *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_in));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    SetChildOsErrorMessage(os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_err));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(write_out));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(exec_control));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -378,7 +369,7 @@
             F_SETFD,
             TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
@@ -387,7 +378,7 @@
     TEMP_FAILURE_RETRY(close(write_out[1]));
     TEMP_FAILURE_RETRY(close(exec_control[0]));
     TEMP_FAILURE_RETRY(close(exec_control[1]));
-    Log::PrintErr("fcntl failed: %s\n", os_error_message);
+    Log::PrintErr("fcntl failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -416,7 +407,7 @@
   }
   pid = TEMP_FAILURE_RETRY(fork());
   if (pid < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     delete[] program_arguments;
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
@@ -481,14 +472,14 @@
   int event_fds[2];
   result = TEMP_FAILURE_RETRY(pipe(event_fds));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -514,10 +505,13 @@
       FDUtils::ReadFromBlocking(
           exec_control[0], &child_errno, sizeof(child_errno));
   if (bytes_read == sizeof(child_errno)) {
-      bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
-                                             os_error_message,
-                                             os_error_message_len);
-      os_error_message[os_error_message_len - 1] = '\0';
+    static const int kMaxMessageSize = 256;
+    char* message = static_cast<char*>(malloc(kMaxMessageSize));
+    bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
+                                           message,
+                                           kMaxMessageSize);
+    message[kMaxMessageSize - 1] = '\0';
+    *os_error_message = message;
   }
   TEMP_FAILURE_RETRY(close(exec_control[0]));
 
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index bd4ed87..01b17a9 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -259,16 +259,8 @@
 dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
 
 
-static char* SafeStrNCpy(char* dest, const char* src, size_t n) {
-  strncpy(dest, src, n);
-  dest[n - 1] = '\0';
-  return dest;
-}
-
-
-static void SetChildOsErrorMessage(char* os_error_message,
-                                   int os_error_message_len) {
-  SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len);
+static void SetChildOsErrorMessage(char** os_error_message) {
+  *os_error_message = strdup(strerror(errno));
 }
 
 
@@ -316,8 +308,7 @@
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_event,
-                   char* os_error_message,
-                   int os_error_message_len) {
+                   char** os_error_message) {
   pid_t pid;
   int read_in[2];  // Pipe for stdout to child process.
   int read_err[2];  // Pipe for stderr to child process.
@@ -327,50 +318,50 @@
 
   bool initialized = ExitCodeHandler::EnsureInitialized();
   if (!initialized) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     Log::PrintErr(
             "Error initializing exit code handler: %s\n",
-            os_error_message);
+            *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_in));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    SetChildOsErrorMessage(os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_err));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(write_out));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(exec_control));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -380,7 +371,7 @@
             F_SETFD,
             TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
@@ -389,7 +380,7 @@
     TEMP_FAILURE_RETRY(close(write_out[1]));
     TEMP_FAILURE_RETRY(close(exec_control[0]));
     TEMP_FAILURE_RETRY(close(exec_control[1]));
-    Log::PrintErr("fcntl failed: %s\n", os_error_message);
+    Log::PrintErr("fcntl failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -418,7 +409,7 @@
   }
   pid = TEMP_FAILURE_RETRY(fork());
   if (pid < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     delete[] program_arguments;
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
@@ -481,14 +472,14 @@
   int event_fds[2];
   result = TEMP_FAILURE_RETRY(pipe(event_fds));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -514,10 +505,13 @@
       FDUtils::ReadFromBlocking(
           exec_control[0], &child_errno, sizeof(child_errno));
   if (bytes_read == sizeof(child_errno)) {
-      bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
-                                             os_error_message,
-                                             os_error_message_len);
-      os_error_message[os_error_message_len - 1] = '\0';
+    static const int kMaxMessageSize = 256;
+    char* message = static_cast<char*>(malloc(kMaxMessageSize));
+    bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
+                                           message,
+                                           kMaxMessageSize);
+    message[kMaxMessageSize - 1] = '\0';
+    *os_error_message = message;
   }
   TEMP_FAILURE_RETRY(close(exec_control[0]));
 
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index aa15940..6256b31 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -258,16 +258,8 @@
 dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
 
 
-static char* SafeStrNCpy(char* dest, const char* src, size_t n) {
-  strncpy(dest, src, n);
-  dest[n - 1] = '\0';
-  return dest;
-}
-
-
-static void SetChildOsErrorMessage(char* os_error_message,
-                                   int os_error_message_len) {
-  SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len);
+static void SetChildOsErrorMessage(char** os_error_message) {
+  *os_error_message = strdup(strerror(errno));
 }
 
 
@@ -315,8 +307,7 @@
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_event,
-                   char* os_error_message,
-                   int os_error_message_len) {
+                   char** os_error_message) {
   pid_t pid;
   int read_in[2];  // Pipe for stdout to child process.
   int read_err[2];  // Pipe for stderr to child process.
@@ -326,49 +317,49 @@
 
   bool initialized = ExitCodeHandler::EnsureInitialized();
   if (!initialized) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     Log::PrintErr("Error initializing exit code handler: %s\n",
-                       os_error_message);
+                       *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_in));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    SetChildOsErrorMessage(os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_err));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(write_out));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(exec_control));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -378,7 +369,7 @@
             F_SETFD,
             TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
@@ -387,7 +378,7 @@
     TEMP_FAILURE_RETRY(close(write_out[1]));
     TEMP_FAILURE_RETRY(close(exec_control[0]));
     TEMP_FAILURE_RETRY(close(exec_control[1]));
-    Log::PrintErr("fcntl failed: %s\n", os_error_message);
+    Log::PrintErr("fcntl failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -416,7 +407,7 @@
   }
   pid = TEMP_FAILURE_RETRY(fork());
   if (pid < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     delete[] program_arguments;
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
@@ -479,14 +470,14 @@
   int event_fds[2];
   result = TEMP_FAILURE_RETRY(pipe(event_fds));
   if (result < 0) {
-    SetChildOsErrorMessage(os_error_message, os_error_message_len);
+    SetChildOsErrorMessage(os_error_message);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
     return errno;
   }
 
@@ -512,10 +503,13 @@
       FDUtils::ReadFromBlocking(
           exec_control[0], &child_errno, sizeof(child_errno));
   if (bytes_read == sizeof(child_errno)) {
-      bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
-                                             os_error_message,
-                                             os_error_message_len);
-      os_error_message[os_error_message_len - 1] = '\0';
+    static const int kMaxMessageSize = 256;
+    char* message = static_cast<char*>(malloc(kMaxMessageSize));
+    bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
+                                           message,
+                                           kMaxMessageSize);
+    message[kMaxMessageSize - 1] = '\0';
+    *os_error_message = message;
   }
   TEMP_FAILURE_RETRY(close(exec_control[0]));
 
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 0a9eb52..624b1f2 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -294,24 +294,27 @@
   CloseProcessPipe(handles4);
 }
 
-static int SetOsErrorMessage(char* os_error_message,
-                             int os_error_message_len) {
+
+static int SetOsErrorMessage(char** os_error_message) {
   int error_code = GetLastError();
+  static const int kMaxMessageLength = 256;
+  wchar_t message[kMaxMessageLength];
   DWORD message_size =
-      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-                    NULL,
-                    error_code,
-                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                    os_error_message,
-                    os_error_message_len,
-                    NULL);
+      FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                     NULL,
+                     error_code,
+                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                     message,
+                     kMaxMessageLength,
+                     NULL);
   if (message_size == 0) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
       Log::PrintErr("FormatMessage failed %d\n", GetLastError());
     }
-    snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code);
+    _snwprintf(message, kMaxMessageLength, L"OS Error %d", error_code);
   }
-  os_error_message[os_error_message_len - 1] = '\0';
+  message[kMaxMessageLength - 1] = '\0';
+  *os_error_message = StringUtils::WideToUtf8(message);
   return error_code;
 }
 
@@ -327,8 +330,7 @@
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_handler,
-                   char* os_error_message,
-                   int os_error_message_len) {
+                   char** os_error_message) {
   HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
   HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
   HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
@@ -339,15 +341,15 @@
   UUID uuid;
   RPC_STATUS status = UuidCreateSequential(&uuid);
   if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
+    SetOsErrorMessage(os_error_message);
     Log::PrintErr("UuidCreateSequential failed %d\n", status);
-    SetOsErrorMessage(os_error_message, os_error_message_len);
     return status;
   }
   RPC_CSTR uuid_string;
   status = UuidToString(&uuid, &uuid_string);
   if (status != RPC_S_OK) {
+    SetOsErrorMessage(os_error_message);
     Log::PrintErr("UuidToString failed %d\n", status);
-    SetOsErrorMessage(os_error_message, os_error_message_len);
     return status;
   }
   for (int i = 0; i < 4; i++) {
@@ -358,52 +360,95 @@
   }
   status = RpcStringFree(&uuid_string);
   if (status != RPC_S_OK) {
+    SetOsErrorMessage(os_error_message);
     Log::PrintErr("RpcStringFree failed %d\n", status);
-    SetOsErrorMessage(os_error_message, os_error_message_len);
     return status;
   }
 
   if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
-    int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
+    int error_code = SetOsErrorMessage(os_error_message);
     CloseProcessPipes(
         stdin_handles, stdout_handles, stderr_handles, exit_handles);
     return error_code;
   }
   if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
-    int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
+    int error_code = SetOsErrorMessage(os_error_message);
     CloseProcessPipes(
         stdin_handles, stdout_handles, stderr_handles, exit_handles);
     return error_code;
   }
   if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) {
-    int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
+    int error_code = SetOsErrorMessage(os_error_message);
     CloseProcessPipes(
         stdin_handles, stdout_handles, stderr_handles, exit_handles);
     return error_code;
   }
   if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) {
-    int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
+    int error_code = SetOsErrorMessage(os_error_message);
     CloseProcessPipes(
         stdin_handles, stdout_handles, stderr_handles, exit_handles);
     return error_code;
   }
 
   // Setup info structures.
-  STARTUPINFO startup_info;
+  STARTUPINFOEX startup_info;
   ZeroMemory(&startup_info, sizeof(startup_info));
-  startup_info.cb = sizeof(startup_info);
-  startup_info.hStdInput = stdin_handles[kReadHandle];
-  startup_info.hStdOutput = stdout_handles[kWriteHandle];
-  startup_info.hStdError = stderr_handles[kWriteHandle];
-  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.StartupInfo.cb = sizeof(startup_info);
+  startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle];
+  startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle];
+  startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle];
+  startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+
+  // Setup the handles to inherit. We only want to inherit the three handles
+  // for stdin, stdout and stderr.
+  SIZE_T size = 0;
+  // The call to determine the size of an attribute list always fails with
+  // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
+  if (!InitializeProcThreadAttributeList(NULL, 1, 0, &size) &&
+      GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+    int error_code = SetOsErrorMessage(os_error_message);
+    CloseProcessPipes(
+        stdin_handles, stdout_handles, stderr_handles, exit_handles);
+    return error_code;
+  }
+  LPPROC_THREAD_ATTRIBUTE_LIST attribute_list =
+      reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
+  ZeroMemory(attribute_list, size);
+  if (!InitializeProcThreadAttributeList(attribute_list, 1, 0, &size)) {
+    int error_code = SetOsErrorMessage(os_error_message);
+    CloseProcessPipes(
+        stdin_handles, stdout_handles, stderr_handles, exit_handles);
+    free(attribute_list);
+    return error_code;
+  }
+  static const int kNumInheritedHandles = 3;
+  HANDLE inherited_handles[kNumInheritedHandles] =
+      { stdin_handles[kReadHandle],
+        stdout_handles[kWriteHandle],
+        stderr_handles[kWriteHandle] };
+  if (!UpdateProcThreadAttribute(attribute_list,
+                                 0,
+                                 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
+                                 inherited_handles,
+                                 kNumInheritedHandles * sizeof(HANDLE),
+                                 NULL,
+                                 NULL)) {
+    DeleteProcThreadAttributeList(attribute_list);
+    int error_code = SetOsErrorMessage(os_error_message);
+    CloseProcessPipes(
+        stdin_handles, stdout_handles, stderr_handles, exit_handles);
+    free(attribute_list);
+    return error_code;
+  }
+  startup_info.lpAttributeList = attribute_list;
 
   PROCESS_INFORMATION process_info;
   ZeroMemory(&process_info, sizeof(process_info));
 
   // Transform input strings to system format.
-  path = StringUtils::Utf8ToSystemString(path);
+  path = StringUtils::Utf8ToConsoleString(path);
   for (int i = 0; i < arguments_length; i++) {
-     arguments[i] = StringUtils::Utf8ToSystemString(arguments[i]);
+     arguments[i] = StringUtils::Utf8ToConsoleString(arguments[i]);
   }
 
   // Compute command-line length.
@@ -415,11 +460,13 @@
   command_line_length += arguments_length + 1;
   static const int kMaxCommandLineLength = 32768;
   if (command_line_length > kMaxCommandLineLength) {
-    int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
+    int error_code = SetOsErrorMessage(os_error_message);
     CloseProcessPipes(
         stdin_handles, stdout_handles, stderr_handles, exit_handles);
     free(const_cast<char*>(path));
     for (int i = 0; i < arguments_length; i++) free(arguments[i]);
+    DeleteProcThreadAttributeList(attribute_list);
+    free(attribute_list);
     return error_code;
   }
 
@@ -445,7 +492,7 @@
   if (environment != NULL) {
     // Convert environment strings to system strings.
     for (intptr_t i = 0; i < environment_length; i++) {
-      environment[i] = StringUtils::Utf8ToSystemString(environment[i]);
+      environment[i] = StringUtils::Utf8ToConsoleString(environment[i]);
     }
 
     // An environment block is a sequence of zero-terminated strings
@@ -473,7 +520,7 @@
   }
 
   if (working_directory != NULL) {
-    working_directory = StringUtils::Utf8ToSystemString(working_directory);
+    working_directory = StringUtils::Utf8ToConsoleString(working_directory);
   }
 
   // Create process.
@@ -482,10 +529,10 @@
                               NULL,   // ProcessAttributes
                               NULL,   // ThreadAttributes
                               TRUE,   // InheritHandles
-                              0,      // CreationFlags
+                              EXTENDED_STARTUPINFO_PRESENT,
                               environment_block,
                               working_directory,
-                              &startup_info,
+                              reinterpret_cast<STARTUPINFO*>(&startup_info),
                               &process_info);
 
   // Deallocate command-line and environment block strings.
@@ -495,8 +542,11 @@
     free(const_cast<char*>(working_directory));
   }
 
+  DeleteProcThreadAttributeList(attribute_list);
+  free(attribute_list);
+
   if (result == 0) {
-    int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
+    int error_code = SetOsErrorMessage(os_error_message);
     CloseProcessPipes(
         stdin_handles, stdout_handles, stderr_handles, exit_handles);
     return error_code;
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index 1e28e52..c378683 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -73,43 +73,40 @@
   Dart_EnterScope();
   Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
   Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
-  Dart_Handle is_server_object = ThrowIfError(Dart_GetNativeArgument(args, 3));
+  bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
   Dart_Handle certificate_name_object =
       ThrowIfError(Dart_GetNativeArgument(args, 4));
+  bool request_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
+  bool require_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6));
+  bool send_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7));
 
   const char* host_name = NULL;
   // TODO(whesse): Is truncating a Dart string containing \0 what we want?
   ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
 
   int64_t port;
-  if (!DartUtils::GetInt64Value(port_object, &port) ||
-      port < 0 || port > 65535) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-      "Illegal port parameter in _SSLFilter.connect"));
+  if (!DartUtils::GetInt64Value(port_object, &port)) {
+    FATAL("The range of port_object was checked in Dart - it cannot fail here");
   }
 
-  if (!Dart_IsBoolean(is_server_object)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-      "Illegal is_server parameter in _SSLFilter.connect"));
-  }
-  bool is_server = DartUtils::GetBooleanValue(is_server_object);
-
   const char* certificate_name = NULL;
-  // If this is a server connection, get the certificate to connect with.
-  // TODO(whesse): Use this parameter for a client certificate as well.
-  if (is_server) {
-    if (!Dart_IsString(certificate_name_object)) {
-      Dart_ThrowException(DartUtils::NewDartArgumentError(
-          "Non-String certificate parameter in _SSLFilter.connect"));
-    }
+  if (Dart_IsString(certificate_name_object)) {
     ThrowIfError(Dart_StringToCString(certificate_name_object,
                                       &certificate_name));
   }
+  // If this is a server connection, it must have a certificate to connect with.
+  ASSERT(!is_server || certificate_name != NULL);
 
   GetFilter(args)->Connect(host_name,
-                              static_cast<int>(port),
-                              is_server,
-                              certificate_name);
+                           static_cast<int>(port),
+                           is_server,
+                           certificate_name,
+                           request_client_certificate,
+                           require_client_certificate,
+                           send_client_certificate);
   Dart_ExitScope();
 }
 
@@ -221,17 +218,30 @@
 }
 
 
-static bool CallBadCertificateCallback(Dart_Handle callback,
-                                       const char* subject_name,
-                                       const char* issuer_name,
-                                       int64_t start_validity,
-                                       int64_t end_validity) {
-  if (callback == NULL || Dart_IsNull(callback)) return false;
+void FUNCTION_NAME(SecureSocket_PeerCertificate)
+    (Dart_NativeArguments args) {
   Dart_EnterScope();
-  Dart_Handle subject_name_object = DartUtils::NewString(subject_name);
-  Dart_Handle issuer_name_object = DartUtils::NewString(issuer_name);
-  Dart_Handle start_validity_int = Dart_NewInteger(start_validity);
-  Dart_Handle end_validity_int = Dart_NewInteger(end_validity);
+  Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
+  Dart_ExitScope();
+}
+
+
+static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
+  PRTime start_validity;
+  PRTime end_validity;
+  SECStatus status =
+      CERT_GetCertTimes(certificate, &start_validity, &end_validity);
+  if (status != SECSuccess) {
+    ThrowPRException("Cannot get validity times from certificate");
+  }
+  int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC;
+  int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC;
+  Dart_Handle subject_name_object =
+      DartUtils::NewString(certificate->subjectName);
+  Dart_Handle issuer_name_object =
+      DartUtils::NewString(certificate->issuerName);
+  Dart_Handle start_epoch_ms_int = Dart_NewInteger(start_epoch_ms);
+  Dart_Handle end_epoch_ms_int = Dart_NewInteger(end_epoch_ms);
 
   Dart_Handle date_class =
       DartUtils::GetDartClass(DartUtils::kCoreLibURL, "Date");
@@ -239,9 +249,9 @@
       DartUtils::NewString("fromMillisecondsSinceEpoch");
 
   Dart_Handle start_validity_date =
-      Dart_New(date_class, from_milliseconds, 1, &start_validity_int);
+      Dart_New(date_class, from_milliseconds, 1, &start_epoch_ms_int);
   Dart_Handle end_validity_date =
-      Dart_New(date_class, from_milliseconds, 1, &end_validity_int);
+      Dart_New(date_class, from_milliseconds, 1, &end_epoch_ms_int);
 
   Dart_Handle x509_class =
       DartUtils::GetDartClass(DartUtils::kIOLibURL, "X509Certificate");
@@ -249,13 +259,7 @@
                               issuer_name_object,
                               start_validity_date,
                               end_validity_date };
-  Dart_Handle certificate = Dart_New(x509_class, Dart_Null(), 4, arguments);
-
-  Dart_Handle result =
-      ThrowIfError(Dart_InvokeClosure(callback, 1, &certificate));
-  bool c_result = Dart_IsBoolean(result) && DartUtils::GetBooleanValue(result);
-  Dart_ExitScope();
-  return c_result;
+  return Dart_New(x509_class, Dart_Null(), 4, arguments);
 }
 
 
@@ -341,21 +345,21 @@
                                       SECMOD_DB,
                                       init_flags);
     if (status != SECSuccess) {
-      ThrowPRException("Unsuccessful NSS_Init call.");
+      ThrowPRException("Failed NSS_Init call.");
     }
 
     status = NSS_SetDomesticPolicy();
     if (status != SECSuccess) {
-      ThrowPRException("Unsuccessful NSS_SetDomesticPolicy call.");
+      ThrowPRException("Failed NSS_SetDomesticPolicy call.");
     }
     // Enable TLS, as well as SSL3 and SSL2.
     status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
     if (status != SECSuccess) {
-      ThrowPRException("Unsuccessful SSL_OptionSetDefault enable TLS call.");
+      ThrowPRException("Failed SSL_OptionSetDefault enable TLS call.");
     }
     status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
     if (status != SECSuccess) {
-      ThrowPRException("Unsuccessful SSL_ConfigServerSessionIDCache call.");
+      ThrowPRException("Failed SSL_ConfigServerSessionIDCache call.");
     }
 
   } else {
@@ -373,36 +377,36 @@
 
 
 SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) {
-  return static_cast<SSLFilter*>(filter)->HandleBadCertificate(fd);
+  SSLFilter* ssl_filter = static_cast<SSLFilter*>(filter);
+  Dart_Handle callback = ssl_filter->bad_certificate_callback();
+  if (callback == NULL || Dart_IsNull(callback)) return SECFailure;
+
+  Dart_EnterScope();
+  Dart_Handle x509_object = ssl_filter->PeerCertificate();
+  Dart_Handle result =
+      ThrowIfError(Dart_InvokeClosure(callback, 1, &x509_object));
+  bool c_result = Dart_IsBoolean(result) && DartUtils::GetBooleanValue(result);
+  Dart_ExitScope();
+  return c_result ? SECSuccess : SECFailure;
 }
 
 
-SECStatus SSLFilter::HandleBadCertificate(PRFileDesc* fd) {
-  ASSERT(fd == filter_);
-  CERTCertificate* certificate = SSL_PeerCertificate(fd);
-  PRTime start_validity;
-  PRTime end_validity;
-  SECStatus status =
-      CERT_GetCertTimes(certificate, &start_validity, &end_validity);
-  if (status != SECSuccess) {
-    ThrowPRException("Cannot get validity times from certificate");
-  }
-  int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC;
-  int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC;
-  bool accept = CallBadCertificateCallback(bad_certificate_callback_,
-                                           certificate->subjectName,
-                                           certificate->issuerName,
-                                           start_epoch_ms,
-                                           end_epoch_ms);
+Dart_Handle SSLFilter::PeerCertificate() {
+  CERTCertificate* certificate = SSL_PeerCertificate(filter_);
+  if (certificate == NULL) return Dart_Null();
+  Dart_Handle x509_object = X509FromCertificate(certificate);
   CERT_DestroyCertificate(certificate);
-  return accept ? SECSuccess : SECFailure;
+  return x509_object;
 }
 
 
 void SSLFilter::Connect(const char* host_name,
                         int port,
                         bool is_server,
-                        const char* certificate_name) {
+                        const char* certificate_name,
+                        bool request_client_certificate,
+                        bool require_client_certificate,
+                        bool send_client_certificate) {
   is_server_ = is_server;
   if (in_handshake_) {
     ThrowException("Connect called while already in handshake state.");
@@ -410,7 +414,7 @@
 
   filter_ = SSL_ImportFD(NULL, filter_);
   if (filter_ == NULL) {
-    ThrowPRException("Unsuccessful SSL_ImportFD call");
+    ThrowPRException("Failed SSL_ImportFD call");
   }
 
   SECStatus status;
@@ -420,6 +424,8 @@
     if (certificate_database == NULL) {
       ThrowPRException("Certificate database cannot be loaded");
     }
+    // TODO(whesse): Switch to a function that looks up certs by nickname,
+    // so that server and client uses of certificateName agree.
     CERTCertificate* certificate = CERT_FindCertByNameString(
         certificate_database,
         const_cast<char*>(certificate_name));
@@ -434,7 +440,7 @@
       if (PR_GetError() == -8177) {
         ThrowPRException("Certificate database password incorrect");
       } else {
-        ThrowPRException("Unsuccessful PK11_FindKeyByAnyCert call."
+        ThrowPRException("Failed PK11_FindKeyByAnyCert call."
                          " Cannot find private key for certificate");
       }
     }
@@ -444,11 +450,41 @@
     CERT_DestroyCertificate(certificate);
     SECKEY_DestroyPrivateKey(key);
     if (status != SECSuccess) {
-      ThrowPRException("Unsuccessful SSL_ConfigSecureServer call");
+      ThrowPRException("Failed SSL_ConfigSecureServer call");
+    }
+
+    if (request_client_certificate) {
+      status = SSL_OptionSet(filter_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
+      if (status != SECSuccess) {
+        ThrowPRException("Failed SSL_OptionSet(REQUEST_CERTIFICATE) call");
+      }
+      PRBool require_cert = require_client_certificate ? PR_TRUE : PR_FALSE;
+      status = SSL_OptionSet(filter_, SSL_REQUIRE_CERTIFICATE, require_cert);
+      if (status != SECSuccess) {
+        ThrowPRException("Failed SSL_OptionSet(REQUIRE_CERTIFICATE) call");
+      }
     }
   } else {  // Client.
     if (SSL_SetURL(filter_, host_name) == -1) {
-      ThrowPRException("Unsuccessful SetURL call");
+      ThrowPRException("Failed SetURL call");
+    }
+
+    // This disables the SSL session cache for client connections.
+    // This resolves issue 7208, but degrades performance.
+    // TODO(7230): Reenable session cache, without breaking client connections.
+    status = SSL_OptionSet(filter_, SSL_NO_CACHE, PR_TRUE);
+    if (status != SECSuccess) {
+      ThrowPRException("Failed SSL_OptionSet(NO_CACHE) call");
+    }
+
+    if (send_client_certificate) {
+      status = SSL_GetClientAuthDataHook(
+          filter_,
+          NSS_GetClientAuthData,
+          static_cast<void*>(const_cast<char*>(certificate_name)));
+      if (status != SECSuccess) {
+        ThrowPRException("Failed SSL_GetClientAuthDataHook call");
+      }
     }
   }
 
@@ -460,7 +496,7 @@
   PRBool as_server = is_server ? PR_TRUE : PR_FALSE;
   status = SSL_ResetHandshake(filter_, as_server);
   if (status != SECSuccess) {
-    ThrowPRException("Unsuccessful SSL_ResetHandshake call");
+    ThrowPRException("Failed SSL_ResetHandshake call");
   }
 
   // SetPeerAddress
@@ -470,12 +506,12 @@
   PRStatus rv = PR_GetHostByName(host_name, host_entry_buffer,
                                  PR_NETDB_BUF_SIZE, &host_entry);
   if (rv != PR_SUCCESS) {
-    ThrowPRException("Unsuccessful PR_GetHostByName call");
+    ThrowPRException("Failed PR_GetHostByName call");
   }
 
   int index = PR_EnumerateHostEnt(0, &host_entry, port, &host_address);
   if (index == -1 || index == 0) {
-    ThrowPRException("Unsuccessful PR_EnumerateHostEnt call");
+    ThrowPRException("Failed PR_EnumerateHostEnt call");
   }
   memio_SetPeerName(filter_, &host_address);
 }
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 520693a..f20ca7d 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -74,18 +74,20 @@
   void Connect(const char* host,
                int port,
                bool is_server,
-               const char* certificate_name);
+               const char* certificate_name,
+               bool request_client_certificate,
+               bool require_client_certificate,
+               bool send_client_certificate);
   void Destroy();
   void Handshake();
   void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
   void RegisterBadCertificateCallback(Dart_Handle callback);
+  Dart_Handle bad_certificate_callback() { return bad_certificate_callback_; }
   static void InitializeLibrary(const char* certificate_database,
                                 const char* password,
                                 bool use_builtin_root_certificates);
-
   intptr_t ProcessBuffer(int bufferIndex);
-
-  SECStatus HandleBadCertificate(PRFileDesc* fd);
+  Dart_Handle PeerCertificate();
 
  private:
   static const int kMemioBufferSize = 20 * KB;
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index c511465..9e79c86 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -37,7 +37,10 @@
   void connect(String hostName,
                int port,
                bool is_server,
-               String certificate_name) native "SecureSocket_Connect";
+               String certificateName,
+               bool requestClientCertificate,
+               bool requireClientCertificate,
+               bool sendClientCertificate) native "SecureSocket_Connect";
 
   void destroy() {
     buffers = null;
@@ -50,6 +53,8 @@
 
   void init() native "SecureSocket_Init";
 
+  X509Certificate get peerCertificate native "SecureSocket_PeerCertificate";
+
   int processBuffer(int bufferIndex) native "SecureSocket_ProcessBuffer";
 
   void registerBadCertificateCallback(Function callback)
diff --git a/runtime/bin/stdio_patch.dart b/runtime/bin/stdio_patch.dart
index bcdc671..5dd5d87 100644
--- a/runtime/bin/stdio_patch.dart
+++ b/runtime/bin/stdio_patch.dart
@@ -3,8 +3,39 @@
 // BSD-style license that can be found in the LICENSE file.
 
 patch class _StdIOUtils {
-  /* patch */ static _getStdioHandle(Socket socket, int num)
-      native "Socket_GetStdioHandle";
-  /* patch */ static _getStdioHandleType(int num)
-      native "File_GetStdioHandleType";
+  static InputStream _getStdioInputStream() {
+    switch (_getStdioHandleType(0)) {
+      case _STDIO_HANDLE_TYPE_TERMINAL:
+      case _STDIO_HANDLE_TYPE_PIPE:
+      case _STDIO_HANDLE_TYPE_SOCKET:
+        Socket s = new _Socket._internalReadOnly();
+        _getStdioHandle(s, 0);
+        s._closed = false;
+        return s.inputStream;
+      case _STDIO_HANDLE_TYPE_FILE:
+        return new _FileInputStream.fromStdio(0);
+      default:
+        throw new FileIOException("Unsupported stdin type");
+    }
+  }
+
+  static OutputStream _getStdioOutputStream(int fd) {
+    assert(fd == 1 || fd == 2);
+    switch (_getStdioHandleType(fd)) {
+      case _STDIO_HANDLE_TYPE_TERMINAL:
+      case _STDIO_HANDLE_TYPE_PIPE:
+      case _STDIO_HANDLE_TYPE_SOCKET:
+        Socket s = new _Socket._internalWriteOnly();
+        _getStdioHandle(s, fd);
+        s._closed = false;
+        return s.outputStream;
+      case _STDIO_HANDLE_TYPE_FILE:
+        return new _FileOutputStream.fromStdio(fd);
+      default:
+        throw new FileIOException("Unsupported stdin type");
+    }
+  }
 }
+
+_getStdioHandle(Socket socket, int num) native "Socket_GetStdioHandle";
+_getStdioHandleType(int num) native "File_GetStdioHandleType";
\ No newline at end of file
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index 70545ab..e655f6c 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -59,10 +59,14 @@
   // conversions are only needed on Windows. If the methods returns a
   // pointer that is different from the input pointer the returned
   // pointer is allocated with malloc and should be freed using free.
-  static const char* SystemStringToUtf8(const char* str);
-  static char* SystemStringToUtf8(char* str);
-  static const char* Utf8ToSystemString(const char* utf8);
-  static char* Utf8ToSystemString(char* utf8);
+  static const char* ConsoleStringToUtf8(const char* str);
+  static char* ConsoleStringToUtf8(char* str);
+  static const char* Utf8ToConsoleString(const char* utf8);
+  static char* Utf8ToConsoleString(char* utf8);
+  static char* WideToUtf8(wchar_t* wide);
+  static const char* WideToUtf8(const wchar_t* wide);
+  static wchar_t* Utf8ToWide(char* utf8);
+  static const wchar_t* Utf8ToWide(const char* utf8);
 };
 
 #endif  // BIN_UTILS_H_
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index ab48f55..5661f74 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -27,18 +27,38 @@
   }
 }
 
-const char* StringUtils::SystemStringToUtf8(const char* str) {
+const char* StringUtils::ConsoleStringToUtf8(const char* str) {
   return str;
 }
 
-const char* StringUtils::Utf8ToSystemString(const char* utf8) {
+const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
   return utf8;
 }
 
-char* StringUtils::SystemStringToUtf8(char* str) {
+char* StringUtils::ConsoleStringToUtf8(char* str) {
   return str;
 }
 
-char* StringUtils::Utf8ToSystemString(char* utf8) {
+char* StringUtils::Utf8ToConsoleString(char* utf8) {
   return utf8;
 }
+
+wchar_t* StringUtils::Utf8ToWide(char* utf8) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+char* StringUtils::WideToUtf8(wchar_t* str) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+const char* StringUtils::WideToUtf8(const wchar_t* str) {
+  UNIMPLEMENTED();
+  return NULL;
+}
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index ab48f55..5661f74 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -27,18 +27,38 @@
   }
 }
 
-const char* StringUtils::SystemStringToUtf8(const char* str) {
+const char* StringUtils::ConsoleStringToUtf8(const char* str) {
   return str;
 }
 
-const char* StringUtils::Utf8ToSystemString(const char* utf8) {
+const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
   return utf8;
 }
 
-char* StringUtils::SystemStringToUtf8(char* str) {
+char* StringUtils::ConsoleStringToUtf8(char* str) {
   return str;
 }
 
-char* StringUtils::Utf8ToSystemString(char* utf8) {
+char* StringUtils::Utf8ToConsoleString(char* utf8) {
   return utf8;
 }
+
+wchar_t* StringUtils::Utf8ToWide(char* utf8) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+char* StringUtils::WideToUtf8(wchar_t* str) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+const char* StringUtils::WideToUtf8(const wchar_t* str) {
+  UNIMPLEMENTED();
+  return NULL;
+}
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index ab48f55..5661f74 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -27,18 +27,38 @@
   }
 }
 
-const char* StringUtils::SystemStringToUtf8(const char* str) {
+const char* StringUtils::ConsoleStringToUtf8(const char* str) {
   return str;
 }
 
-const char* StringUtils::Utf8ToSystemString(const char* utf8) {
+const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
   return utf8;
 }
 
-char* StringUtils::SystemStringToUtf8(char* str) {
+char* StringUtils::ConsoleStringToUtf8(char* str) {
   return str;
 }
 
-char* StringUtils::Utf8ToSystemString(char* utf8) {
+char* StringUtils::Utf8ToConsoleString(char* utf8) {
   return utf8;
 }
+
+wchar_t* StringUtils::Utf8ToWide(char* utf8) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+char* StringUtils::WideToUtf8(wchar_t* str) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+const char* StringUtils::WideToUtf8(const wchar_t* str) {
+  UNIMPLEMENTED();
+  return NULL;
+}
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index f9603f8..cf8f93a 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -8,21 +8,21 @@
 #include "bin/log.h"
 
 static void FormatMessageIntoBuffer(DWORD code,
-                                    char* buffer,
+                                    wchar_t* buffer,
                                     int buffer_length) {
   DWORD message_size =
-      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-                    NULL,
-                    code,
-                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                    buffer,
-                    buffer_length,
-                    NULL);
+      FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                     NULL,
+                     code,
+                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                     buffer,
+                     buffer_length,
+                     NULL);
   if (message_size == 0) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
       Log::PrintErr("FormatMessage failed %d\n", GetLastError());
     }
-    snprintf(buffer, buffer_length, "OS Error %d", code);
+    _snwprintf(buffer, buffer_length, L"OS Error %d", code);
   }
   buffer[buffer_length - 1] = '\0';
 }
@@ -32,9 +32,11 @@
   set_code(GetLastError());
 
   static const int kMaxMessageLength = 256;
-  char message[kMaxMessageLength];
+  wchar_t message[kMaxMessageLength];
   FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
-  SetMessage(message);
+  char* utf8 = StringUtils::WideToUtf8(message);
+  SetMessage(utf8);
+  free(utf8);
 }
 
 void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
@@ -42,41 +44,63 @@
   set_code(code);
 
   static const int kMaxMessageLength = 256;
-  char message[kMaxMessageLength];
+  wchar_t message[kMaxMessageLength];
   FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
-  SetMessage(message);
+  char* utf8 = StringUtils::WideToUtf8(message);
+  SetMessage(utf8);
+  free(utf8);
 }
 
-char* StringUtils::SystemStringToUtf8(char* str) {
+char* StringUtils::ConsoleStringToUtf8(char* str) {
   int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
   wchar_t* unicode = new wchar_t[len+1];
   MultiByteToWideChar(CP_ACP, 0, str, -1, unicode, len);
   unicode[len] = '\0';
-  len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
-  char* utf8 = reinterpret_cast<char*>(malloc(len+1));
-  WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf8, len, NULL, NULL);
-  utf8[len] = '\0';
+  char* utf8 = StringUtils::WideToUtf8(unicode);
   delete[] unicode;
   return utf8;
 }
 
-char* StringUtils::Utf8ToSystemString(char* utf8) {
-  int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
-  wchar_t* unicode = new wchar_t[len+1];
-  MultiByteToWideChar(CP_UTF8, 0, utf8, -1, unicode, len);
-  unicode[len] = '\0';
-  len = WideCharToMultiByte(CP_ACP, 0, unicode, -1, NULL, 0, NULL, NULL);
-  char* ansi = reinterpret_cast<char*>(malloc(len+1));
+char* StringUtils::Utf8ToConsoleString(char* utf8) {
+  wchar_t* unicode = Utf8ToWide(utf8);
+  int len = WideCharToMultiByte(CP_ACP, 0, unicode, -1, NULL, 0, NULL, NULL);
+  char* ansi = reinterpret_cast<char*>(malloc(len + 1));
   WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, len, NULL, NULL);
   ansi[len] = '\0';
-  delete[] unicode;
+  free(unicode);
   return ansi;
 }
 
-const char* StringUtils::Utf8ToSystemString(const char* utf8) {
-  return const_cast<const char*>(Utf8ToSystemString(const_cast<char*>(utf8)));
+char* StringUtils::WideToUtf8(wchar_t* wide) {
+  int len = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL);
+  char* utf8 = reinterpret_cast<char*>(malloc(len + 1));
+  WideCharToMultiByte(CP_UTF8, 0, wide, -1, utf8, len, NULL, NULL);
+  utf8[len] = '\0';
+  return utf8;
 }
 
-const char* StringUtils::SystemStringToUtf8(const char* str) {
-  return const_cast<const char*>(Utf8ToSystemString(const_cast<char*>(str)));
+
+wchar_t* StringUtils::Utf8ToWide(char* utf8) {
+  int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
+  wchar_t* unicode =
+      reinterpret_cast<wchar_t*>(malloc((len + 1) * sizeof(wchar_t)));
+  MultiByteToWideChar(CP_UTF8, 0, utf8, -1, unicode, len);
+  unicode[len] = '\0';
+  return unicode;
+}
+
+const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
+  return const_cast<const char*>(Utf8ToConsoleString(const_cast<char*>(utf8)));
+}
+
+const char* StringUtils::ConsoleStringToUtf8(const char* str) {
+  return const_cast<const char*>(ConsoleStringToUtf8(const_cast<char*>(str)));
+}
+
+const char* StringUtils::WideToUtf8(const wchar_t* wide) {
+  return const_cast<const char*>(WideToUtf8(const_cast<wchar_t*>(wide)));
+}
+
+const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
+  return const_cast<const wchar_t*>(Utf8ToWide(const_cast<char*>(utf8)));
 }
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index ac4dc52..8b273a4 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -17,7 +17,7 @@
       AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(type_arguments.IsNull() ||
          (type_arguments.IsInstantiated() && (type_arguments.Length() == 1)));
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
   intptr_t len = length.Value();
   if (len < 0 || len > Array::kMaxElements) {
     const String& error = String::Handle(String::NewFormatted(
@@ -35,7 +35,7 @@
 
 DEFINE_NATIVE_ENTRY(ObjectArray_getIndexed, 2) {
   const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     GrowableArray<const Object*> arguments;
     arguments.Add(&index);
@@ -47,7 +47,7 @@
 
 DEFINE_NATIVE_ENTRY(ObjectArray_setIndexed, 3) {
   const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
   const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(2));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     GrowableArray<const Object*> arguments;
@@ -68,10 +68,10 @@
 // ObjectArray src, int srcStart, int dstStart, int count.
 DEFINE_NATIVE_ENTRY(ObjectArray_copyFromObjectArray, 5) {
   const Array& dest = Array::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Array, source, arguments->NativeArgAt(1));
-  GET_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(2));
-  GET_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(3));
-  GET_NATIVE_ARGUMENT(Smi, count, arguments->NativeArgAt(4));
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, source, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, count, arguments->NativeArgAt(4));
   intptr_t icount = count.Value();
   if (icount < 0) {
     GrowableArray<const Object*> args;
diff --git a/runtime/lib/bool_patch.dart b/runtime/lib/bool_patch.dart
new file mode 100644
index 0000000..fd84119
--- /dev/null
+++ b/runtime/lib/bool_patch.dart
@@ -0,0 +1,14 @@
+// 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.
+
+// Dart core library.
+
+patch class bool {
+  
+  /* patch */ int get hashCode {
+    return this ? 1231 : 1237;
+  }
+
+  /* patch */ bool operator ==(other) => identical(this, other);
+}
diff --git a/runtime/lib/byte_array.cc b/runtime/lib/byte_array.cc
index 11daaf1..0d98f98 100644
--- a/runtime/lib/byte_array.cc
+++ b/runtime/lib/byte_array.cc
@@ -43,111 +43,112 @@
 }
 
 
-#define GETTER_ARGUMENTS(ArrayT, ValueT)                                \
-  GET_NATIVE_ARGUMENT(ArrayT, array, arguments->NativeArgAt(0));        \
-  GET_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
+#define GETTER_ARGUMENTS(ArrayT, ValueT)                                       \
+  GET_NON_NULL_NATIVE_ARGUMENT(ArrayT, array, arguments->NativeArgAt(0));      \
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
 
 
-#define SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT)                       \
-  GET_NATIVE_ARGUMENT(ArrayT, array, arguments->NativeArgAt(0));        \
-  GET_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));           \
-  GET_NATIVE_ARGUMENT(ObjectT, value_object, arguments->NativeArgAt(2));
+#define SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT)                              \
+  GET_NON_NULL_NATIVE_ARGUMENT(ArrayT, array, arguments->NativeArgAt(0));      \
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));         \
+  GET_NON_NULL_NATIVE_ARGUMENT(                                                \
+      ObjectT, value_object, arguments->NativeArgAt(2));
 
 
-#define GETTER(ArrayT, ObjectT, ValueT)                                 \
-  GETTER_ARGUMENTS(ArrayT, ValueT);                                     \
-  RangeCheck(array, index.Value() * sizeof(ValueT), sizeof(ValueT));    \
-  ValueT result = array.At(index.Value());                              \
+#define GETTER(ArrayT, ObjectT, ValueT)                                        \
+  GETTER_ARGUMENTS(ArrayT, ValueT);                                            \
+  RangeCheck(array, index.Value() * sizeof(ValueT), sizeof(ValueT));           \
+  ValueT result = array.At(index.Value());                                     \
   return ObjectT::New(result);
 
 
-#define SETTER(ArrayT, ObjectT, Getter, ValueT)                         \
-  SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT);                            \
-  RangeCheck(array, index.Value() * sizeof(ValueT), sizeof(ValueT));    \
-  ValueT value = value_object.Getter();                                 \
-  array.SetAt(index.Value(), value);                                    \
+#define SETTER(ArrayT, ObjectT, Getter, ValueT)                                \
+  SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT);                                   \
+  RangeCheck(array, index.Value() * sizeof(ValueT), sizeof(ValueT));           \
+  ValueT value = value_object.Getter();                                        \
+  array.SetAt(index.Value(), value);                                           \
   return Object::null();
 
 
-#define UNALIGNED_GETTER(ArrayT, ObjectT, ValueT)                       \
-  GETTER_ARGUMENTS(ArrayT, ValueT);                                     \
-  RangeCheck(array, index.Value(), sizeof(ValueT));                     \
-  ValueT result;                                                        \
-  ByteArray::Copy(&result, array, index.Value(), sizeof(ValueT));       \
+#define UNALIGNED_GETTER(ArrayT, ObjectT, ValueT)                              \
+  GETTER_ARGUMENTS(ArrayT, ValueT);                                            \
+  RangeCheck(array, index.Value(), sizeof(ValueT));                            \
+  ValueT result;                                                               \
+  ByteArray::Copy(&result, array, index.Value(), sizeof(ValueT));              \
   return ObjectT::New(result);
 
 
-#define UNALIGNED_SETTER(ArrayT, ObjectT, Getter, ValueT)               \
-  SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT);                            \
-  RangeCheck(array, index.Value(), sizeof(ValueT));                     \
-  ValueT src = value_object.Getter();                                   \
-  ByteArray::Copy(array, index.Value(), &src, sizeof(ValueT));          \
+#define UNALIGNED_SETTER(ArrayT, ObjectT, Getter, ValueT)                      \
+  SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT);                                   \
+  RangeCheck(array, index.Value(), sizeof(ValueT));                            \
+  ValueT src = value_object.Getter();                                          \
+  ByteArray::Copy(array, index.Value(), &src, sizeof(ValueT));                 \
   return Integer::New(index.Value() + sizeof(ValueT));
 
 
-#define UINT64_TO_INTEGER(value, integer)                               \
-  if (value > static_cast<uint64_t>(Mint::kMaxValue)) {                 \
-    result = BigintOperations::NewFromUint64(value);                    \
-  } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) {           \
-    result = Mint::New(value);                                          \
-  } else {                                                              \
-    result = Smi::New(value);                                           \
+#define UINT64_TO_INTEGER(value, integer)                                      \
+  if (value > static_cast<uint64_t>(Mint::kMaxValue)) {                        \
+    result = BigintOperations::NewFromUint64(value);                           \
+  } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) {                  \
+    result = Mint::New(value);                                                 \
+  } else {                                                                     \
+    result = Smi::New(value);                                                  \
   }
 
 
-#define GETTER_UINT64(ArrayT)                                           \
-  GETTER_ARGUMENTS(ArrayT, uint64_t);                                   \
-  intptr_t size = sizeof(uint64_t);                                     \
-  RangeCheck(array, index.Value() * size, size);                        \
-  uint64_t value = array.At(index.Value());                             \
-  Integer& result = Integer::Handle();                                  \
-  UINT64_TO_INTEGER(value, result);                                     \
+#define GETTER_UINT64(ArrayT)                                                  \
+  GETTER_ARGUMENTS(ArrayT, uint64_t);                                          \
+  intptr_t size = sizeof(uint64_t);                                            \
+  RangeCheck(array, index.Value() * size, size);                               \
+  uint64_t value = array.At(index.Value());                                    \
+  Integer& result = Integer::Handle();                                         \
+  UINT64_TO_INTEGER(value, result);                                            \
   return result.raw();
 
 
-#define UNALIGNED_GETTER_UINT64(ArrayT)                                 \
-  GETTER_ARGUMENTS(ArrayT, uint64_t);                                   \
-  RangeCheck(array, index.Value(), sizeof(uint64_t));                   \
-  uint64_t value;                                                       \
-  ByteArray::Copy(&value, array, index.Value(), sizeof(uint64_t));      \
-  Integer& result = Integer::Handle();                                  \
-  UINT64_TO_INTEGER(value, result);                                     \
+#define UNALIGNED_GETTER_UINT64(ArrayT)                                        \
+  GETTER_ARGUMENTS(ArrayT, uint64_t);                                          \
+  RangeCheck(array, index.Value(), sizeof(uint64_t));                          \
+  uint64_t value;                                                              \
+  ByteArray::Copy(&value, array, index.Value(), sizeof(uint64_t));             \
+  Integer& result = Integer::Handle();                                         \
+  UINT64_TO_INTEGER(value, result);                                            \
   return result.raw();
 
 
-#define INTEGER_TO_UINT64(integer, uint64)                              \
-  if (integer.IsBigint()) {                                             \
-    Bigint& bigint = Bigint::Handle();                                  \
-    bigint ^= integer.raw();                                            \
-    ASSERT(BigintOperations::FitsIntoUint64(bigint));                   \
-    value = BigintOperations::AbsToUint64(bigint);                      \
-  } else {                                                              \
-    ASSERT(integer.IsMint() || integer.IsSmi());                        \
-    value = integer.AsInt64Value();                                     \
-  }                                                                     \
+#define INTEGER_TO_UINT64(integer, uint64)                                     \
+  if (integer.IsBigint()) {                                                    \
+    Bigint& bigint = Bigint::Handle();                                         \
+    bigint ^= integer.raw();                                                   \
+    ASSERT(BigintOperations::FitsIntoUint64(bigint));                          \
+    value = BigintOperations::AbsToUint64(bigint);                             \
+  } else {                                                                     \
+    ASSERT(integer.IsMint() || integer.IsSmi());                               \
+    value = integer.AsInt64Value();                                            \
+  }                                                                            \
 
 
-#define SETTER_UINT64(ArrayT)                                           \
-  SETTER_ARGUMENTS(ArrayT, Integer, uint64_t);                          \
-  intptr_t size = sizeof(uint64_t);                                     \
-  RangeCheck(array, index.Value() * size, size);                        \
-  uint64_t value;                                                       \
-  INTEGER_TO_UINT64(value_object, value);                               \
-  array.SetAt(index.Value(), value);                                    \
+#define SETTER_UINT64(ArrayT)                                                  \
+  SETTER_ARGUMENTS(ArrayT, Integer, uint64_t);                                 \
+  intptr_t size = sizeof(uint64_t);                                            \
+  RangeCheck(array, index.Value() * size, size);                               \
+  uint64_t value;                                                              \
+  INTEGER_TO_UINT64(value_object, value);                                      \
+  array.SetAt(index.Value(), value);                                           \
   return Object::null();
 
 
-#define UNALIGNED_SETTER_UINT64(ArrayT)                                 \
-  SETTER_ARGUMENTS(ArrayT, Integer, uint64_t);                          \
-  RangeCheck(array, index.Value(), sizeof(uint64_t));                   \
-  uint64_t value;                                                       \
-  INTEGER_TO_UINT64(value_object, value);                               \
-  ByteArray::Copy(array, index.Value(), &value, sizeof(uint64_t));      \
+#define UNALIGNED_SETTER_UINT64(ArrayT)                                        \
+  SETTER_ARGUMENTS(ArrayT, Integer, uint64_t);                                 \
+  RangeCheck(array, index.Value(), sizeof(uint64_t));                          \
+  uint64_t value;                                                              \
+  INTEGER_TO_UINT64(value_object, value);                                      \
+  ByteArray::Copy(array, index.Value(), &value, sizeof(uint64_t));             \
   return Integer::New(index.Value() + sizeof(uint64_t));
 
 
 DEFINE_NATIVE_ENTRY(ByteArray_getLength, 1) {
-  GET_NATIVE_ARGUMENT(ByteArray, array, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(ByteArray, array, arguments->NativeArgAt(0));
   return Smi::New(array.Length());
 }
 
@@ -254,10 +255,10 @@
 
 DEFINE_NATIVE_ENTRY(ByteArray_setRange, 5) {
   ByteArray& dst = ByteArray::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(1));
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(2));
-  GET_NATIVE_ARGUMENT(ByteArray, src, arguments->NativeArgAt(3));
-  GET_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(4));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, dst_start, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(ByteArray, src, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(4));
   intptr_t length_value = length.Value();
   intptr_t src_start_value = src_start.Value();
   intptr_t dst_start_value = dst_start.Value();
@@ -278,7 +279,7 @@
 // Int8Array
 
 DEFINE_NATIVE_ENTRY(Int8Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int8Array::kMaxElements);
   return Int8Array::New(len);
@@ -286,7 +287,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Int8Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int8Array::kMaxElements);
   int8_t* bytes = OS::AllocateAlignedArray<int8_t>(
@@ -312,7 +313,7 @@
 // Uint8Array
 
 DEFINE_NATIVE_ENTRY(Uint8Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint8Array::kMaxElements);
   return Uint8Array::New(len);
@@ -320,7 +321,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Uint8Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint8Array::kMaxElements);
   uint8_t* bytes = OS::AllocateAlignedArray<uint8_t>(
@@ -346,7 +347,7 @@
 // Uint8ClampedArray
 
 DEFINE_NATIVE_ENTRY(Uint8ClampedArray_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint8ClampedArray::kMaxElements);
   return Uint8ClampedArray::New(len);
@@ -354,7 +355,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Uint8ClampedArray_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint8ClampedArray::kMaxElements);
   uint8_t* bytes = OS::AllocateAlignedArray<uint8_t>(
@@ -380,7 +381,7 @@
 // Int16Array
 
 DEFINE_NATIVE_ENTRY(Int16Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int16Array::kMaxElements);
   return Int16Array::New(len);
@@ -388,7 +389,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Int16Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int16Array::kMaxElements);
   int16_t* bytes = OS::AllocateAlignedArray<int16_t>(
@@ -414,7 +415,7 @@
 // Uint16Array
 
 DEFINE_NATIVE_ENTRY(Uint16Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint16Array::kMaxElements);
   return Uint16Array::New(len);
@@ -422,7 +423,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Uint16Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint16Array::kMaxElements);
   uint16_t* bytes = OS::AllocateAlignedArray<uint16_t>(
@@ -448,7 +449,7 @@
 // Int32Array
 
 DEFINE_NATIVE_ENTRY(Int32Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int32Array::kMaxElements);
   return Int32Array::New(len);
@@ -456,7 +457,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Int32Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int32Array::kMaxElements);
   int32_t* bytes = OS::AllocateAlignedArray<int32_t>(
@@ -482,7 +483,7 @@
 // Uint32Array
 
 DEFINE_NATIVE_ENTRY(Uint32Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint32Array::kMaxElements);
   return Uint32Array::New(len);
@@ -490,7 +491,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Uint32Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint32Array::kMaxElements);
   uint32_t* bytes = OS::AllocateAlignedArray<uint32_t>(
@@ -516,7 +517,7 @@
 // Int64Array
 
 DEFINE_NATIVE_ENTRY(Int64Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int64Array::kMaxElements);
   return Int64Array::New(len);
@@ -524,7 +525,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Int64Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Int64Array::kMaxElements);
   int64_t* bytes = OS::AllocateAlignedArray<int64_t>(
@@ -550,7 +551,7 @@
 // Uint64Array
 
 DEFINE_NATIVE_ENTRY(Uint64Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint64Array::kMaxElements);
   return Uint64Array::New(len);
@@ -558,7 +559,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Uint64Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Uint64Array::kMaxElements);
   uint64_t* bytes = OS::AllocateAlignedArray<uint64_t>(
@@ -584,7 +585,7 @@
 // Float32Array
 
 DEFINE_NATIVE_ENTRY(Float32Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Float32Array::kMaxElements);
   return Float32Array::New(len);
@@ -592,7 +593,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Float32Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Float32Array::kMaxElements);
   float* bytes = OS::AllocateAlignedArray<float>(
@@ -618,7 +619,7 @@
 // Float64Array
 
 DEFINE_NATIVE_ENTRY(Float64Array_new, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Float64Array::kMaxElements);
   return Float64Array::New(len);
@@ -626,7 +627,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Float64Array_newTransferable, 1) {
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Float64Array::kMaxElements);
   double* bytes = OS::AllocateAlignedArray<double>(
diff --git a/runtime/lib/byte_array.dart b/runtime/lib/byte_array.dart
index 96715db..61be89d 100644
--- a/runtime/lib/byte_array.dart
+++ b/runtime/lib/byte_array.dart
@@ -59,7 +59,8 @@
     return new _Int16Array.transferable(length);
   }
 
-  /* patch */ factory Int16List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Int16List.view(ByteArray array,
+                                     [int start = 0, int length]) {
     return new _Int16ArrayView(array, start, length);
   }
 }
@@ -74,7 +75,8 @@
     return new _Uint16Array.transferable(length);
   }
 
-  /* patch */ factory Uint16List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Uint16List.view(ByteArray array,
+                                      [int start = 0, int length]) {
     return new _Uint16ArrayView(array, start, length);
   }
 }
@@ -89,7 +91,8 @@
     return new _Int32Array.transferable(length);
   }
 
-  /* patch */ factory Int32List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Int32List.view(ByteArray array,
+                                     [int start = 0, int length]) {
     return new _Int32ArrayView(array, start, length);
   }
 }
@@ -104,7 +107,8 @@
     return new _Uint32Array.transferable(length);
   }
 
-  /* patch */ factory Uint32List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Uint32List.view(ByteArray array,
+                                      [int start = 0, int length]) {
     return new _Uint32ArrayView(array, start, length);
   }
 }
@@ -119,7 +123,8 @@
     return new _Int64Array.transferable(length);
   }
 
-  /* patch */ factory Int64List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Int64List.view(ByteArray array,
+                                     [int start = 0, int length]) {
     return new _Int64ArrayView(array, start, length);
   }
 }
@@ -134,7 +139,8 @@
     return new _Uint64Array.transferable(length);
   }
 
-  /* patch */ factory Uint64List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Uint64List.view(ByteArray array,
+                                      [int start = 0, int length]) {
     return new _Uint64ArrayView(array, start, length);
   }
 }
@@ -149,7 +155,8 @@
     return new _Float32Array.transferable(length);
   }
 
-  /* patch */ factory Float32List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Float32List.view(ByteArray array,
+                                       [int start = 0, int length]) {
     return new _Float32ArrayView(array, start, length);
   }
 }
@@ -164,7 +171,8 @@
     return new _Float64Array.transferable(length);
   }
 
-  /* patch */ factory Float64List.view(ByteArray array, [int start = 0, int length]) {
+  /* patch */ factory Float64List.view(ByteArray array,
+                                       [int start = 0, int length]) {
     return new _Float64ArrayView(array, start, length);
   }
 }
diff --git a/runtime/lib/date.cc b/runtime/lib/date.cc
index 7bd1a72..ad66673 100644
--- a/runtime/lib/date.cc
+++ b/runtime/lib/date.cc
@@ -16,7 +16,8 @@
 static int32_t kMaxAllowedSeconds = 2100000000;
 
 DEFINE_NATIVE_ENTRY(DateNatives_timeZoneName, 1) {
-  GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      Integer, dart_seconds, arguments->NativeArgAt(0));
   int64_t seconds = dart_seconds.AsInt64Value();
   if (seconds < 0 || seconds > kMaxAllowedSeconds) {
     GrowableArray<const Object*> args;
@@ -29,7 +30,8 @@
 
 
 DEFINE_NATIVE_ENTRY(DateNatives_timeZoneOffsetInSeconds, 1) {
-  GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      Integer, dart_seconds, arguments->NativeArgAt(0));
   int64_t seconds = dart_seconds.AsInt64Value();
   if (seconds < 0 || seconds > kMaxAllowedSeconds) {
     GrowableArray<const Object*> args;
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index abadf12..350fbde 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -30,7 +30,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_add, 2) {
   double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_add %f + %f\n", left, right);
@@ -41,7 +41,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_sub, 2) {
   double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_sub %f - %f\n", left, right);
@@ -52,7 +52,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_mul, 2) {
   double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_mul %f * %f\n", left, right);
@@ -63,7 +63,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_div, 2) {
   double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_div %f / %f\n", left, right);
@@ -74,7 +74,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_trunc_div, 2) {
   double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_trunc_div %f ~/ %f\n", left, right);
@@ -85,7 +85,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_modulo, 2) {
   double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
 
   double remainder = fmod_ieee(left, right);
@@ -105,7 +105,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_remainder, 2) {
   double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   return Double::New(fmod_ieee(left, right));
 }
@@ -113,7 +113,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_greaterThan, 2) {
   const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
   bool result = right.IsNull() ? false : (left.value() > right.value());
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_greaterThan %s > %s\n",
@@ -125,14 +125,14 @@
 
 DEFINE_NATIVE_ENTRY(Double_greaterThanFromInteger, 2) {
   const Double& right = Double::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   return Bool::Get(left.AsDoubleValue() > right.value());
 }
 
 
 DEFINE_NATIVE_ENTRY(Double_equal, 2) {
   const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
   bool result = right.IsNull() ? false : (left.value() == right.value());
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_equal %s == %s\n",
@@ -144,7 +144,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_equalToInteger, 2) {
   const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1));
   return Bool::Get(left.value() == right.AsDoubleValue());
 }
 
@@ -174,7 +174,8 @@
 DEFINE_NATIVE_ENTRY(Double_pow, 2) {
   const double operand =
       Double::CheckedHandle(arguments->NativeArgAt(0)).value();
-  GET_NATIVE_ARGUMENT(Double, exponent_object, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      Double, exponent_object, arguments->NativeArgAt(1));
   const double exponent = exponent_object.value();
   return Double::New(pow(operand, exponent));
 }
@@ -205,7 +206,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Double_parse, 1) {
-  GET_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
   const String& dummy_key = String::Handle(Symbols::Empty());
   Scanner scanner(value, dummy_key);
   const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
@@ -265,7 +266,7 @@
   static const double kUpperBoundary = 1e21;
 
   const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1));
   double d = arg.value();
   intptr_t fraction_digits_value = fraction_digits.Value();
   if (0 <= fraction_digits_value && fraction_digits_value <= 20
@@ -283,7 +284,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_toStringAsExponential, 2) {
   const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1));
   double d = arg.value();
   intptr_t fraction_digits_value = fraction_digits.Value();
   if (-1 <= fraction_digits_value && fraction_digits_value <= 20) {
@@ -301,7 +302,7 @@
 
 DEFINE_NATIVE_ENTRY(Double_toStringAsPrecision, 2) {
   const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, precision, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, precision, arguments->NativeArgAt(1));
   double d = arg.value();
   intptr_t precision_value = precision.Value();
   if (1 <= precision_value && precision_value <= 21) {
diff --git a/runtime/lib/error.cc b/runtime/lib/error.cc
index 247b555..ea39065 100644
--- a/runtime/lib/error.cc
+++ b/runtime/lib/error.cc
@@ -82,7 +82,7 @@
 // Arg0: index of the case clause token into which we fall through.
 // Return value: none, throws an exception.
 DEFINE_NATIVE_ENTRY(FallThroughError_throwNew, 1) {
-  GET_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
   intptr_t fallthrough_pos = smi_pos.Value();
 
   // Allocate a new instance of type FallThroughError.
@@ -114,8 +114,8 @@
 // Arg1: class name of the abstract class that cannot be instantiated.
 // Return value: none, throws an exception.
 DEFINE_NATIVE_ENTRY(AbstractClassInstantiationError_throwNew, 2) {
-  GET_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(String, class_name, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, class_name, arguments->NativeArgAt(1));
   intptr_t error_pos = smi_pos.Value();
 
   // Allocate a new instance of type AbstractClassInstantiationError.
@@ -141,13 +141,19 @@
 }
 
 
+// TODO(regis): This helper is used to compile a throw when a call cannot be
+// resolved at compile time. The thrown instance of NoSuchMethodError is of a
+// different type than a NoSuchMethodError thrown at runtime. This should be
+// merged.
+//
 // Allocate and throw NoSuchMethodError.
 // Arg0: index of the call that was not resolved at compile time.
 // Arg1: name of the method that was not resolved at compile time.
 // Return value: none, throws an exception.
 DEFINE_NATIVE_ENTRY(NoSuchMethodError_throwNew, 2) {
-  GET_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(String, function_name, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      String, function_name, arguments->NativeArgAt(1));
   intptr_t call_pos = smi_pos.Value();
   // Allocate a new instance of type NoSuchMethodError.
   const Instance& error = Instance::Handle(
diff --git a/runtime/lib/error.dart b/runtime/lib/error.dart
index b3ce3b7..7aa960f 100644
--- a/runtime/lib/error.dart
+++ b/runtime/lib/error.dart
@@ -91,7 +91,8 @@
 }
 
 
-// TODO(regis): This class will change once mirrors are available.
+// TODO(regis): This class should be removed and the corresponding class in the
+// core lib should be used.
 class NoSuchMethodErrorImplementation implements NoSuchMethodError {
   factory NoSuchMethodErrorImplementation._uninstantiable() {
     throw new UnsupportedError(
diff --git a/runtime/lib/growable_array.cc b/runtime/lib/growable_array.cc
index 6168d75..ac679af 100644
--- a/runtime/lib/growable_array.cc
+++ b/runtime/lib/growable_array.cc
@@ -17,7 +17,7 @@
       AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(type_arguments.IsNull() ||
          (type_arguments.IsInstantiated() && (type_arguments.Length() == 1)));
-  GET_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
   if ((data.Length() <= 0)) {
     const Integer& index = Integer::Handle(Integer::New(data.Length()));
     GrowableArray<const Object*> args;
@@ -34,7 +34,7 @@
 DEFINE_NATIVE_ENTRY(GrowableObjectArray_getIndexed, 2) {
   const GrowableObjectArray& array =
       GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     GrowableArray<const Object*> args;
     args.Add(&index);
@@ -48,13 +48,13 @@
 DEFINE_NATIVE_ENTRY(GrowableObjectArray_setIndexed, 3) {
   const GrowableObjectArray& array =
       GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     GrowableArray<const Object*> args;
     args.Add(&index);
     Exceptions::ThrowByType(Exceptions::kRange, args);
   }
-  GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(2));
   array.SetAt(index.Value(), value);
   return Object::null();
 }
@@ -77,7 +77,7 @@
 DEFINE_NATIVE_ENTRY(GrowableObjectArray_setLength, 2) {
   const GrowableObjectArray& array =
       GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
   if ((length.Value() < 0) || (length.Value() > array.Capacity())) {
     GrowableArray<const Object*> args;
     args.Add(&length);
@@ -91,7 +91,7 @@
 DEFINE_NATIVE_ENTRY(GrowableObjectArray_setData, 2) {
   const GrowableObjectArray& array =
       GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
   ASSERT(data.Length() > 0);
   array.SetData(data);
   return Object::null();
diff --git a/runtime/lib/identical_patch.dart b/runtime/lib/identical_patch.dart
new file mode 100644
index 0000000..218b3c8
--- /dev/null
+++ b/runtime/lib/identical_patch.dart
@@ -0,0 +1,7 @@
+// 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.
+
+patch bool identical(Object a, Object b) {
+  throw new Error('Should not reach the body of identical');  
+}
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index f81e078..0b10b38a 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -38,7 +38,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) {
   const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
@@ -53,7 +53,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) {
   const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
@@ -68,7 +68,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) {
   const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
@@ -83,7 +83,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) {
   const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
@@ -98,7 +98,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) {
   const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
@@ -113,7 +113,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) {
   const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
@@ -128,7 +128,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) {
   const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   ASSERT(!right_int.IsZero());
@@ -140,7 +140,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) {
   const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(right_int));
   if (FLAG_trace_intrinsified_natives) {
@@ -159,7 +159,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) {
   const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
@@ -172,7 +172,7 @@
 
 DEFINE_NATIVE_ENTRY(Integer_equalToInteger, 2) {
   const Integer& left = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(left));
   ASSERT(CheckInteger(right));
   if (FLAG_trace_intrinsified_natives) {
@@ -184,7 +184,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Integer_parse, 1) {
-  GET_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
   const String& dummy_key = String::Handle(Symbols::Empty());
   Scanner scanner(value, dummy_key);
   const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
@@ -257,7 +257,7 @@
 
 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) {
   const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(amount));
   ASSERT(CheckInteger(value));
   const Integer& result = Integer::Handle(
@@ -269,7 +269,7 @@
 
 DEFINE_NATIVE_ENTRY(Smi_shlFromInt, 2) {
   const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(amount));
   ASSERT(CheckInteger(value));
   if (FLAG_trace_intrinsified_natives) {
diff --git a/runtime/lib/invocation_mirror_patch.dart b/runtime/lib/invocation_mirror_patch.dart
index 4fb83f9..e81fe50 100644
--- a/runtime/lib/invocation_mirror_patch.dart
+++ b/runtime/lib/invocation_mirror_patch.dart
@@ -7,16 +7,51 @@
   static final int GETTER = 1;
   static final int SETTER = 2;
 
+  // TODO(regis): Compute lazily the value of these fields, and save the
+  // arguments passed into _allocateInvocationMirror.
+
   final String memberName;
   final List positionalArguments;
-  final Map<String,dynamic> namedArguments = null;
+  final Map<String, dynamic> namedArguments;
 
   final int _type;
 
-  _InvocationMirror(this.memberName, this._type, this.positionalArguments);
+  _InvocationMirror(this.memberName,
+                    this._type,
+                    this.positionalArguments,
+                    this.namedArguments);
 
-  static _allocateInvocationMirror(name, arguments) {
-    return new _InvocationMirror(name, METHOD, arguments);
+  static _allocateInvocationMirror(String name,
+                                   List argumentsDescriptor,
+                                   List arguments) {
+    var memberName;
+    var type;
+    if (name.startsWith("get:")) {
+      type = GETTER;
+      memberName = name.substring(4);
+    } else if (name.startsWith("set:")) {
+      type = SETTER;
+      memberName = name.substring(4).concat("=");
+    } else {
+      type = METHOD;
+      memberName = name;
+    }
+    // Exclude receiver.
+    int numArguments = argumentsDescriptor[0] - 1;
+    int numPositionalArguments = argumentsDescriptor[1] - 1;
+    int numNamedArguments = numArguments - numPositionalArguments;
+    List positionalArguments = arguments.getRange(1, numPositionalArguments);
+    Map<String, dynamic> namedArguments;
+    if (numNamedArguments > 0) {
+      namedArguments = new Map<String, dynamic>();
+      for (int i = 0; i < numNamedArguments; i++) {
+        String arg_name = argumentsDescriptor[2 + 2*i];
+        var arg_value = arguments[argumentsDescriptor[3 + 2*i]];
+        namedArguments[arg_name] = arg_value;
+      }
+    }
+    return new _InvocationMirror(memberName, type,
+                                 positionalArguments, namedArguments);
   }
 
   bool get isMethod => _type == METHOD;
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 3585ba9..abb15ba 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -125,17 +125,17 @@
 
 
 DEFINE_NATIVE_ENTRY(ReceivePortImpl_closeInternal, 1) {
-  GET_NATIVE_ARGUMENT(Smi, id, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, id, arguments->NativeArgAt(0));
   PortMap::ClosePort(id.Value());
   return Object::null();
 }
 
 
 DEFINE_NATIVE_ENTRY(SendPortImpl_sendInternal_, 3) {
-  GET_NATIVE_ARGUMENT(Smi, send_id, arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, reply_id, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, send_id, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, reply_id, arguments->NativeArgAt(1));
   // TODO(iposva): Allow for arbitrary messages to be sent.
-  GET_NATIVE_ARGUMENT(Instance, obj, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, obj, arguments->NativeArgAt(2));
 
   uint8_t* data = NULL;
   MessageWriter writer(&data, &allocator);
@@ -398,7 +398,7 @@
 
 
 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) {
-  GET_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
   bool throw_exception = false;
   Function& func = Function::Handle();
   if (closure.IsClosure()) {
@@ -427,7 +427,7 @@
 
 
 DEFINE_NATIVE_ENTRY(isolate_spawnUri, 1) {
-  GET_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0));
 
   // Canonicalize the uri with respect to the current isolate.
   char* error = NULL;
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 451b219..ad3864f 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -127,3 +127,37 @@
 
 patch spawnUri(String uri) native "isolate_spawnUri";
 
+patch class Timer {
+  /* patch */ factory Timer(int milliseconds, void callback(Timer timer)) {
+    if (_TimerFactory._factory == null) {
+      throw new UnsupportedError("Timer interface not supported.");
+    }
+    return _TimerFactory._factory(milliseconds, callback, false);
+  }
+
+  /**
+   * Creates a new repeating timer. The [callback] is invoked every
+   * [milliseconds] millisecond until cancelled.
+   */
+  /* patch */ factory Timer.repeating(int milliseconds,
+                                      void callback(Timer timer)) {
+    if (_TimerFactory._factory == null) {
+      throw new UnsupportedError("Timer interface not supported.");
+    }
+    return _TimerFactory._factory(milliseconds, callback, true);
+  }
+}
+
+typedef Timer _TimerFactoryClosure(int milliseconds,
+                                   void callback(Timer timer),
+                                   bool repeating);
+
+class _TimerFactory {
+  static _TimerFactoryClosure _factory;
+}
+
+// TODO(ahe): Warning: this is NOT called by Dartium. Instead, it sets
+// [_TimerFactory._factory] directly.
+void _setTimerFactoryClosure(_TimerFactoryClosure closure) {
+  _TimerFactory._factory = closure;
+}
diff --git a/runtime/lib/lib_sources.gypi b/runtime/lib/lib_sources.gypi
index 28c9afd..3de2cde 100644
--- a/runtime/lib/lib_sources.gypi
+++ b/runtime/lib/lib_sources.gypi
@@ -6,6 +6,7 @@
 
 {
   'sources': [
+    'bool_patch.dart',
     'date.cc',
     'date_patch.dart',
     'array.cc',
@@ -22,6 +23,7 @@
     'function_patch.dart',
     'growable_array.cc',
     'growable_array.dart',
+    'identical_patch.dart',
     'immutable_map.dart',
     'integers.cc',
     'integers.dart',
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index 5a434c4..1116dd36 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -16,53 +16,53 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(Math_sqrt, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(sqrt(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_sin, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(sin(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_cos, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(cos(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_tan, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(tan(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_asin, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(asin(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_acos, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(acos(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_atan, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(atan(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_atan2, 2) {
-  GET_NATIVE_ARGUMENT(Double, operand1, arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Double, operand2, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand1, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand2, arguments->NativeArgAt(1));
   return Double::New(atan2_ieee(operand1.value(), operand2.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_exp, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(exp(operand.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Math_log, 1) {
-  GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(log(operand.value()));
 }
 
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index afd1bc5..fce7051 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -20,7 +20,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) {
-  GET_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0));
 
   // Get the port id from the SendPort instance.
   const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port));
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 6f1fef5..3b06b58 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -17,36 +17,39 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Object_noSuchMethod, 3) {
-  const Instance& instance =
-      Instance::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(String, function_name, arguments->NativeArgAt(1));
-  GET_NATIVE_ARGUMENT(Array, func_args, arguments->NativeArgAt(2));
-  const Object& null_object = Object::Handle(Object::null());
-  GrowableArray<const Object*> dart_arguments(4);
+DEFINE_NATIVE_ENTRY(Object_noSuchMethod, 5) {
+  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, is_method, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, member_name, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, func_args, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      Instance, func_named_args, arguments->NativeArgAt(4));
+  GrowableArray<const Object*> dart_arguments(5);
   dart_arguments.Add(&instance);
-  dart_arguments.Add(&function_name);
+  dart_arguments.Add(&member_name);
   dart_arguments.Add(&func_args);
-  dart_arguments.Add(&null_object);
+  dart_arguments.Add(&func_named_args);
 
-  // Report if a function with same name (but different arguments) has been
-  // found.
-  Class& instance_class = Class::Handle(instance.clazz());
-  Function& function =
-      Function::Handle(instance_class.LookupDynamicFunction(function_name));
-  while (function.IsNull()) {
-    instance_class = instance_class.SuperClass();
-    if (instance_class.IsNull()) break;
-    function = instance_class.LookupDynamicFunction(function_name);
-  }
-  if (!function.IsNull()) {
-    const int total_num_parameters = function.NumParameters();
-    const Array& array = Array::Handle(Array::New(total_num_parameters - 1));
-    // Skip receiver.
-    for (int i = 1; i < total_num_parameters; i++) {
-      array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i)));
+  if (is_method.value()) {
+    // Report if a function with same name (but different arguments) has been
+    // found.
+    Class& instance_class = Class::Handle(instance.clazz());
+    Function& function =
+        Function::Handle(instance_class.LookupDynamicFunction(member_name));
+    while (function.IsNull()) {
+      instance_class = instance_class.SuperClass();
+      if (instance_class.IsNull()) break;
+      function = instance_class.LookupDynamicFunction(member_name);
     }
-    dart_arguments.Add(&array);
+    if (!function.IsNull()) {
+      const int total_num_parameters = function.NumParameters();
+      const Array& array = Array::Handle(Array::New(total_num_parameters - 1));
+      // Skip receiver.
+      for (int i = 1; i < total_num_parameters; i++) {
+        array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i)));
+      }
+      dart_arguments.Add(&array);
+    }
   }
   Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments);
   return Object::null();
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index 401d94f..d29a4ae 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -23,13 +23,17 @@
   // A statically dispatched version of Object.toString.
   static String _toString(obj) native "Object_toString";
 
-  dynamic _noSuchMethod(String functionName, List args)
+  _noSuchMethod(bool isMethod,
+                String memberName,
+                List arguments,
+                Map<String, dynamic> namedArguments)
       native "Object_noSuchMethod";
 
-  /* patch */ dynamic noSuchMethod(InvocationMirror invocation) {
-    var methodName = invocation.memberName;
-    var args = invocation.positionalArguments;
-    return _noSuchMethod(methodName, args);
+  /* patch */ noSuchMethod(InvocationMirror invocation) {
+    return _noSuchMethod(invocation.isMethod,
+                         invocation.memberName,
+                         invocation.positionalArguments,
+                         invocation.namedArguments);
   }
 
   /* patch */ Type get runtimeType native "Object_runtimeType";
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 969d5ff..f55767c 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -15,9 +15,11 @@
 DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_factory, 4) {
   ASSERT(AbstractTypeArguments::CheckedHandle(
       arguments->NativeArgAt(0)).IsNull());
-  GET_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
-  GET_NATIVE_ARGUMENT(Instance, handle_multi_line, arguments->NativeArgAt(2));
-  GET_NATIVE_ARGUMENT(Instance, handle_ignore_case, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      Instance, handle_multi_line, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      Instance, handle_ignore_case, arguments->NativeArgAt(3));
   bool ignore_case = handle_ignore_case.raw() == Bool::True();
   bool multi_line = handle_multi_line.raw() == Bool::True();
   return Jscre::Compile(pattern, multi_line, ignore_case);
@@ -65,8 +67,8 @@
 DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_ExecuteMatch, 3) {
   const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  GET_NATIVE_ARGUMENT(String, str, arguments->NativeArgAt(1));
-  GET_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, str, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
   return Jscre::Execute(regexp, str, start_index.Value());
 }
 
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 8f7b028..528a179 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -13,7 +13,7 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 1) {
-  GET_NATIVE_ARGUMENT(Array, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, a, arguments->NativeArgAt(0));
   // TODO(srdjan): Check that parameterized type is an int.
   Zone* zone = isolate->current_zone();
   intptr_t array_len = a.Length();
@@ -53,8 +53,8 @@
 
 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) {
   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
-  GET_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
 
   intptr_t start = start_obj.Value();
   intptr_t end = end_obj.Value();
@@ -65,8 +65,8 @@
 DEFINE_NATIVE_ENTRY(OneByteString_substringUnchecked, 3) {
   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(receiver.IsOneByteString());
-  GET_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
-  GET_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
 
   const intptr_t start = start_obj.Value();
   const intptr_t end = end_obj.Value();
@@ -79,7 +79,7 @@
   const String& receiver = String::CheckedHandle(isolate,
                                                  arguments->NativeArgAt(0));
   ASSERT(receiver.IsOneByteString());
-  GET_NATIVE_ARGUMENT(Smi, smi_split_code, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_split_code, arguments->NativeArgAt(1));
   const intptr_t len = receiver.Length();
   const intptr_t split_code = smi_split_code.Value();
   const GrowableObjectArray& result = GrowableObjectArray::Handle(
@@ -94,7 +94,7 @@
                                               start,
                                               (i - start),
                                               Heap::kNew);
-      result.Add(isolate, str);
+      result.Add(str);
       start = i + 1;
     }
   }
@@ -102,7 +102,7 @@
                                           start,
                                           (i - start),
                                           Heap::kNew);
-  result.Add(isolate, str);
+  result.Add(str);
   return result.raw();
 }
 
@@ -145,7 +145,7 @@
 
 DEFINE_NATIVE_ENTRY(String_charAt, 2) {
   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
   uint32_t value = StringValueAt(receiver, index);
   ASSERT(value <= 0x10FFFF);
   return Symbols::FromCharCode(value);
@@ -153,7 +153,7 @@
 
 DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) {
   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
 
   int32_t value = StringValueAt(receiver, index);
   ASSERT(value >= 0);
@@ -164,7 +164,7 @@
 
 DEFINE_NATIVE_ENTRY(String_concat, 2) {
   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1));
   return String::Concat(receiver, b);
 }
 
@@ -184,7 +184,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Strings_concatAll, 1) {
-  GET_NATIVE_ARGUMENT(Array, strings, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, strings, arguments->NativeArgAt(0));
   ASSERT(!strings.IsNull());
   // Check that the array contains strings.
   Instance& elem = Instance::Handle();
diff --git a/runtime/lib/weak_property.cc b/runtime/lib/weak_property.cc
index 657b42c..80da580 100644
--- a/runtime/lib/weak_property.cc
+++ b/runtime/lib/weak_property.cc
@@ -11,8 +11,8 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(WeakProperty_new, 2) {
-  GET_NATIVE_ARGUMENT(Instance, key, arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, key, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(1));
   const WeakProperty& weak_property = WeakProperty::Handle(WeakProperty::New());
   weak_property.set_key(key);
   weak_property.set_value(value);
@@ -21,20 +21,23 @@
 
 
 DEFINE_NATIVE_ENTRY(WeakProperty_getKey, 1) {
-  GET_NATIVE_ARGUMENT(WeakProperty, weak_property, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      WeakProperty, weak_property, arguments->NativeArgAt(0));
   return weak_property.key();
 }
 
 
 DEFINE_NATIVE_ENTRY(WeakProperty_getValue, 1) {
-  GET_NATIVE_ARGUMENT(WeakProperty, weak_property, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      WeakProperty, weak_property, arguments->NativeArgAt(0));
   return weak_property.value();
 }
 
 
 DEFINE_NATIVE_ENTRY(WeakProperty_setValue, 2) {
-  GET_NATIVE_ARGUMENT(WeakProperty, weak_property, arguments->NativeArgAt(0));
-  GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(
+      WeakProperty, weak_property, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(1));
   weak_property.set_value(value);
   return Object::null();
 }
diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc
index 32b4812..261fdaf 100644
--- a/runtime/vm/assembler.cc
+++ b/runtime/vm/assembler.cc
@@ -151,7 +151,7 @@
 void AssemblerBuffer::EmitObject(const Object& object) {
   // Since we are going to store the handle as part of the fixup information
   // the handle needs to be a zone handle.
-  ASSERT(object.IsZoneHandle());
+  ASSERT(object.IsNotTemporaryScopedHandle());
   ASSERT(object.IsOld());
   EmitFixup(new PatchCodeWithHandle(pointer_offsets_, object));
   cursor_ += kWordSize;  // Reserve space for pointer.
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 72f84ed..017c98f 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -1554,7 +1554,7 @@
   if (object.IsSmi() || object.IsNull()) {
     movl(dst, Immediate(reinterpret_cast<int32_t>(object.raw())));
   } else {
-    ASSERT(object.IsZoneHandle());
+    ASSERT(object.IsNotTemporaryScopedHandle());
     ASSERT(object.IsOld());
     AssemblerBuffer::EnsureCapacity ensured(&buffer_);
     EmitUint8(0xB8 + dst);
@@ -1567,7 +1567,7 @@
   if (object.IsSmi() || object.IsNull()) {
     pushl(Immediate(reinterpret_cast<int32_t>(object.raw())));
   } else {
-    ASSERT(object.IsZoneHandle());
+    ASSERT(object.IsNotTemporaryScopedHandle());
     ASSERT(object.IsOld());
     AssemblerBuffer::EnsureCapacity ensured(&buffer_);
     EmitUint8(0x68);
@@ -1580,7 +1580,7 @@
   if (object.IsSmi() || object.IsNull()) {
     cmpl(reg, Immediate(reinterpret_cast<int32_t>(object.raw())));
   } else {
-    ASSERT(object.IsZoneHandle());
+    ASSERT(object.IsNotTemporaryScopedHandle());
     ASSERT(object.IsOld());
     AssemblerBuffer::EnsureCapacity ensured(&buffer_);
     if (reg == EAX) {
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 04feed8..075a73c 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -1652,7 +1652,7 @@
   if (object.IsSmi() || object.IsNull()) {
     movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
   } else {
-    ASSERT(object.IsZoneHandle());
+    ASSERT(object.IsNotTemporaryScopedHandle());
     ASSERT(object.IsOld());
     AssemblerBuffer::EnsureCapacity ensured(&buffer_);
     EmitRegisterREX(dst, REX_W);
@@ -1666,7 +1666,7 @@
   if (object.IsSmi() || object.IsNull()) {
     movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
   } else {
-    ASSERT(object.IsZoneHandle());
+    ASSERT(object.IsNotTemporaryScopedHandle());
     ASSERT(object.IsOld());
     LoadObject(TMP, object);
     movq(dst, TMP);
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index f3267ab..1be3a90 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -303,7 +303,7 @@
  public:
   LiteralNode(intptr_t token_pos, const Instance& literal)
       : AstNode(token_pos), literal_(literal) {
-    ASSERT(literal_.IsZoneHandle());
+    ASSERT(literal_.IsNotTemporaryScopedHandle());
     ASSERT(literal_.IsSmi() || literal_.IsOld());
 #if defined(DEBUG)
     if (literal_.IsString()) {
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 24c8884..a7bd996 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -14,7 +14,7 @@
 // List of bootstrap native entry points used in the core dart library.
 #define BOOTSTRAP_NATIVE_LIST(V)                                               \
   V(Object_toString, 1)                                                        \
-  V(Object_noSuchMethod, 3)                                                    \
+  V(Object_noSuchMethod, 5)                                                    \
   V(Object_runtimeType, 1)                                                     \
   V(AbstractType_toString, 1)                                                  \
   V(Integer_bitAndFromInteger, 2)                                              \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index c7e2ad1..69f033e 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -436,9 +436,8 @@
   }
   const Class& target_class = Class::Handle(type.type_class());
   String& target_class_name = String::Handle(target_class.Name());
-  const String& period = String::Handle(Symbols::Dot());
   String& target_name = String::Handle(
-      String::Concat(target_class_name, period));
+      String::Concat(target_class_name, Symbols::DotHandle()));
   const String& identifier = String::Handle(factory.RedirectionIdentifier());
   if (!identifier.IsNull()) {
     target_name = String::Concat(target_name, identifier);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 6b84f7b..78f0625 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1000,6 +1000,64 @@
 }
 
 
+// Handle a miss of a megamorphic cache.
+//   Arg0: Receiver.
+//   Arg1: ICData object.
+//   Arg2: Arguments descriptor array.
+
+//   Returns: target instructions to call or null if the
+// InstanceFunctionLookup stub should be used (e.g., to invoke no such
+// method and implicit closures)..
+DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
+  ASSERT(arguments.ArgCount() ==
+     kMegamorphicCacheMissHandlerRuntimeEntry.argument_count());
+  const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
+  const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
+  const Array& descriptor = Array::CheckedHandle(arguments.ArgAt(2));
+  const String& name = String::Handle(ic_data.target_name());
+  const MegamorphicCache& cache = MegamorphicCache::Handle(
+      isolate->megamorphic_cache_table()->Lookup(name, descriptor));
+  Class& cls = Class::Handle(receiver.clazz());
+  // For lookups treat null as an instance of class Object.
+  if (cls.IsNullClass()) {
+    cls = isolate->object_store()->object_class();
+  }
+  ASSERT(!cls.IsNull());
+  if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) {
+    OS::Print("Megamorphic IC miss, class=%s, function=%s\n",
+              cls.ToCString(), name.ToCString());
+  }
+
+  intptr_t arg_count =
+      Smi::Cast(Object::Handle(descriptor.At(0))).Value();
+  intptr_t named_arg_count =
+      arg_count - Smi::Cast(Object::Handle(descriptor.At(1))).Value();
+  const Function& target = Function::Handle(
+      Resolver::ResolveDynamicForReceiverClass(cls,
+                                               name,
+                                               arg_count,
+                                               named_arg_count));
+
+  Instructions& instructions = Instructions::Handle();
+  if (!target.IsNull()) {
+    if (!target.HasCode()) {
+      const Error& error =
+          Error::Handle(Compiler::CompileFunction(target));
+      if (!error.IsNull()) Exceptions::PropagateError(error);
+    }
+    ASSERT(target.HasCode());
+    instructions = Code::Handle(target.CurrentCode()).instructions();
+  }
+  arguments.SetReturn(instructions);
+  if (instructions.IsNull()) return;
+
+  cache.EnsureCapacity();
+  const Smi& class_id = Smi::Handle(Smi::New(cls.id()));
+  cache.Insert(class_id, target);
+  return;
+}
+
+
 // Updates IC data for two arguments. Used by the equality operation when
 // the control flow bypasses regular inline cache (null arguments).
 //   Arg0: Receiver object.
@@ -1126,9 +1184,9 @@
                                getter_function_name,
                                kNumArguments,
                                kNumNamedArguments));
-  Code& code = Code::Handle();
+  const Object& null_object = Object::Handle();
   if (function.IsNull()) {
-    arguments.SetReturn(code);
+    arguments.SetReturn(null_object);
     return;  // No getter function found so can't be an implicit closure.
   }
   GrowableArray<const Object*> invoke_arguments(0);
@@ -1141,7 +1199,7 @@
   if (result.IsError()) {
     if (result.IsUnhandledException()) {
       // If the getter throws an exception, treat as no such method.
-      arguments.SetReturn(code);
+      arguments.SetReturn(null_object);
       return;
     } else {
       Exceptions::PropagateError(Error::Cast(result));
@@ -1168,7 +1226,6 @@
 
   // TODO(regis): Resolve and invoke "call" method, if existing.
 
-  const Object& null_object = Object::Handle();
   dart_arguments.Add(&result);
   dart_arguments.Add(&function_name);
   dart_arguments.Add(&function_args);
@@ -1207,7 +1264,7 @@
   ASSERT(arguments.ArgCount() ==
          kInvokeImplicitClosureFunctionRuntimeEntry.argument_count());
   const Instance& closure = Instance::CheckedHandle(arguments.ArgAt(0));
-  const Array& arg_descriptor = Array::CheckedHandle(arguments.ArgAt(1));
+  const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1));
   const Array& func_arguments = Array::CheckedHandle(arguments.ArgAt(2));
   const Function& function = Function::Handle(Closure::function(closure));
   ASSERT(!function.IsNull());
@@ -1223,24 +1280,24 @@
   const Instructions& instrs = Instructions::Handle(code.instructions());
   ASSERT(!instrs.IsNull());
 
-  // Receiver parameter has already been skipped by caller.
   // The closure object is passed as implicit first argument to closure
   // functions, since it may be needed to throw a NoSuchMethodError, in case
   // the wrong number of arguments is passed.
-  GrowableArray<const Object*> invoke_arguments(func_arguments.Length() + 1);
+  // Replace the original receiver in the arguments array by the closure.
+  GrowableArray<const Object*> invoke_arguments(func_arguments.Length());
   invoke_arguments.Add(&closure);
-  for (intptr_t i = 0; i < func_arguments.Length(); i++) {
+  for (intptr_t i = 1; i < func_arguments.Length(); i++) {
     const Object& value = Object::Handle(func_arguments.At(i));
     invoke_arguments.Add(&value);
   }
 
-  // Now Call the invoke stub which will invoke the closure.
+  // Now call the invoke stub which will invoke the closure.
   DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>(
       StubCode::InvokeDartCodeEntryPoint());
   ASSERT(context.isolate() == Isolate::Current());
   const Object& result = Object::Handle(
       entrypoint(instrs.EntryPoint(),
-                 arg_descriptor,
+                 args_descriptor,
                  invoke_arguments.data(),
                  context));
   CheckResultError(result);
@@ -1259,12 +1316,9 @@
   const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
   const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
   const String& original_function_name = String::Handle(ic_data.target_name());
-  ASSERT(!Array::CheckedHandle(arguments.ArgAt(2)).IsNull());
+  const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2));
   const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3));
   // Allocate an InvocationMirror object.
-  // TODO(regis): Fill in the InvocationMirror object correctly at
-  // this point we do not deal with named arguments and treat them
-  // all as positional.
   const Library& core_lib = Library::Handle(Library::CoreLibrary());
   const String& invocation_mirror_name = String::Handle(
       Symbols::InvocationMirror());
@@ -1278,8 +1332,9 @@
                                     allocation_function_name,
                                     Resolver::kIsQualified));
   ASSERT(!allocation_function.IsNull());
-  GrowableArray<const Object*> allocation_arguments(2);
+  GrowableArray<const Object*> allocation_arguments(3);
   allocation_arguments.Add(&original_function_name);
+  allocation_arguments.Add(&orig_arguments_desc);
   allocation_arguments.Add(&orig_arguments);
   const Array& kNoArgumentNames = Array::Handle();
   const Object& invocation_mirror = Object::Handle(
@@ -1311,25 +1366,17 @@
 // A non-closure object was invoked as a closure, so call the "call" method
 // on it.
 // Arg0: non-closure object.
-// Arg1: arguments array.
-// TODO(regis): Rename this entry?
-DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) {
+// Arg1: arguments descriptor.
+// Arg2: arguments array, including non-closure object.
+DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) {
   ASSERT(arguments.ArgCount() ==
-         kReportObjectNotClosureRuntimeEntry.argument_count());
+         kInvokeNonClosureRuntimeEntry.argument_count());
   const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
-  const Array& function_args = Array::CheckedHandle(arguments.ArgAt(1));
+  const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1));
+  const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2));
+
+  // Resolve and invoke "call" method, if existing.
   const String& function_name = String::Handle(Symbols::Call());
-  GrowableArray<const Object*> dart_arguments(5);
-
-  // TODO(regis): Resolve and invoke "call" method, if existing.
-
-  const Object& null_object = Object::Handle();
-  dart_arguments.Add(&instance);
-  dart_arguments.Add(&function_name);
-  dart_arguments.Add(&function_args);
-  dart_arguments.Add(&null_object);
-
-  // Report if a function "call" with different arguments has been found.
   Class& instance_class = Class::Handle(instance.clazz());
   Function& function =
       Function::Handle(instance_class.LookupDynamicFunction(function_name));
@@ -1339,14 +1386,47 @@
     function = instance_class.LookupDynamicFunction(function_name);
   }
   if (!function.IsNull()) {
-    const int total_num_parameters = function.NumParameters();
-    const Array& array = Array::Handle(Array::New(total_num_parameters - 1));
-    // Skip receiver.
-    for (int i = 1; i < total_num_parameters; i++) {
-      array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i)));
+    if (!function.HasCode()) {
+      const Error& error = Error::Handle(Compiler::CompileFunction(function));
+      if (!error.IsNull()) {
+        Exceptions::PropagateError(error);
+      }
     }
-    dart_arguments.Add(&array);
+    const Code& code = Code::Handle(function.CurrentCode());
+    ASSERT(!code.IsNull());
+    const Instructions& instrs = Instructions::Handle(code.instructions());
+    ASSERT(!instrs.IsNull());
+
+    // The non-closure object is passed as implicit first argument (receiver).
+    // It is already included in the arguments array.
+    GrowableArray<const Object*> invoke_arguments(function_args.Length());
+    for (intptr_t i = 0; i < function_args.Length(); i++) {
+      const Object& value = Object::Handle(function_args.At(i));
+      invoke_arguments.Add(&value);
+    }
+
+    // Now call the invoke stub which will invoke the call method.
+    DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>(
+        StubCode::InvokeDartCodeEntryPoint());
+    const Context& context = Context::ZoneHandle(
+        Isolate::Current()->object_store()->empty_context());
+    const Object& result = Object::Handle(
+        entrypoint(instrs.EntryPoint(),
+                   args_descriptor,
+                   invoke_arguments.data(),
+                   context));
+    CheckResultError(result);
+    arguments.SetReturn(result);
+    return;
   }
+  const Object& null_object = Object::Handle();
+  GrowableArray<const Object*> dart_arguments(5);
+  dart_arguments.Add(&instance);
+  dart_arguments.Add(&function_name);
+  dart_arguments.Add(&function_args);
+  dart_arguments.Add(&null_object);
+  // If a function "call" with different arguments exists, it will have been
+  // invoked above, so no need to handle this case here.
   Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments);
   UNREACHABLE();
 }
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index de97dc5..87011a9 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -37,10 +37,11 @@
 DECLARE_RUNTIME_ENTRY(InstantiateTypeArguments);
 DECLARE_RUNTIME_ENTRY(InvokeImplicitClosureFunction);
 DECLARE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction);
+DECLARE_RUNTIME_ENTRY(MegamorphicCacheMissHandler);
 DECLARE_RUNTIME_ENTRY(OptimizeInvokedFunction);
 DECLARE_RUNTIME_ENTRY(TraceICCall);
 DECLARE_RUNTIME_ENTRY(PatchStaticCall);
-DECLARE_RUNTIME_ENTRY(ReportObjectNotClosure);
+DECLARE_RUNTIME_ENTRY(InvokeNonClosure);
 DECLARE_RUNTIME_ENTRY(ResolveImplicitClosureFunction);
 DECLARE_RUNTIME_ENTRY(ResolveImplicitClosureThroughGetter);
 DECLARE_RUNTIME_ENTRY(ReThrow);
diff --git a/runtime/vm/code_generator_test.cc b/runtime/vm/code_generator_test.cc
index 90d1e09..4b18bdf 100644
--- a/runtime/vm/code_generator_test.cc
+++ b/runtime/vm/code_generator_test.cc
@@ -396,7 +396,7 @@
   function.set_parameter_types(Array::Handle(Array::New(num_params)));
   function.set_parameter_names(Array::Handle(Array::New(num_params)));
   const Type& param_type = Type::Handle(Type::DynamicType());
-  for (int i = 0; i < num_params - 1; i++) {
+  for (int i = 0; i < num_params; i++) {
     function.SetParameterTypeAt(i, param_type);
   }
   const String& native_name =
@@ -465,6 +465,55 @@
     Smi::New(0 + 1 + 1 + 2 + 3))
 
 
+// Tested Dart code:
+//   int sum(a, b, c) native: "TestNonNullSmiSum";
+// The native entry TestNonNullSmiSum implements sum natively.
+CODEGEN_TEST_GENERATE(NativeNonNullSumCodegen, test) {
+  SequenceNode* node_seq = test->node_sequence();
+  const int num_params = 3;
+  LocalScope* local_scope = node_seq->scope();
+  local_scope->AddVariable(NewTestLocalVariable("a"));
+  local_scope->AddVariable(NewTestLocalVariable("b"));
+  local_scope->AddVariable(NewTestLocalVariable("c"));
+  ASSERT(local_scope->num_variables() == num_params);
+  const Function& function = test->function();
+  function.set_is_native(true);
+  function.set_num_fixed_parameters(num_params);
+  ASSERT(!function.HasOptionalParameters());
+  function.set_parameter_types(Array::Handle(Array::New(num_params)));
+  function.set_parameter_names(Array::Handle(Array::New(num_params)));
+  const Type& param_type = Type::Handle(Type::DynamicType());
+  for (int i = 0; i < num_params; i++) {
+    function.SetParameterTypeAt(i, param_type);
+  }
+  const String& native_name =
+      String::ZoneHandle(Symbols::New("TestNonNullSmiSum"));
+  NativeFunction native_function =
+      reinterpret_cast<NativeFunction>(TestNonNullSmiSum);
+  node_seq->Add(new ReturnNode(kPos,
+                               new NativeBodyNode(kPos,
+                                                  function,
+                                                  native_name,
+                                                  native_function)));
+}
+
+
+// Tested Dart code, calling function sum declared above:
+//   return sum(1, null, 3);
+CODEGEN_TEST2_GENERATE(StaticNonNullSumCallCodegen, function, test) {
+  SequenceNode* node_seq = test->node_sequence();
+  ArgumentListNode* arguments = new ArgumentListNode(kPos);
+  arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(1))));
+  arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle()));
+  arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
+  node_seq->Add(new ReturnNode(kPos,
+                               new StaticCallNode(kPos, function, arguments)));
+}
+CODEGEN_TEST2_RUN(StaticNonNullSumCallCodegen,
+                  NativeNonNullSumCodegen,
+                  Smi::New(1 + 3))
+
+
 // Test allocation of dart objects.
 CODEGEN_TEST_GENERATE(AllocateNewObjectCodegen, test) {
   const char* kScriptChars =
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index c82be17..6e4fb44 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -550,6 +550,7 @@
 
 
 RawError* Compiler::CompileAllFunctions(const Class& cls) {
+  Isolate* isolate = Isolate::Current();
   Error& error = Error::Handle();
   Array& functions = Array::Handle(cls.functions());
   Function& func = Function::Handle();
@@ -565,6 +566,8 @@
     if (!func.HasCode() &&
         !func.is_abstract() &&
         !func.IsRedirectingFactory()) {
+      StackZone zone(isolate);
+      HANDLESCOPE(isolate);
       error = CompileFunction(func);
       if (!error.IsNull()) {
         return error.raw();
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index d37c2d7..d6ca37e 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -23,6 +23,8 @@
 
 namespace dart {
 
+DEFINE_FLAG(bool, heap_profile_initialize, false,
+            "Writes a heap profile on isolate initialization.");
 DECLARE_FLAG(bool, print_bootstrap);
 DECLARE_FLAG(bool, print_class_table);
 DECLARE_FLAG(bool, trace_isolates);
@@ -167,13 +169,19 @@
     reader.ReadFullSnapshot();
     if (FLAG_trace_isolates) {
       isolate->heap()->PrintSizes();
+      isolate->megamorphic_cache_table()->PrintSizes();
     }
     if (FLAG_print_bootstrap) {
       PrintLibrarySources(isolate);
     }
   }
 
+  if (FLAG_heap_profile_initialize) {
+    isolate->heap()->ProfileToFile("initialize");
+  }
+
   StubCode::Init(isolate);
+  isolate->megamorphic_cache_table()->InitMissHandler();
   isolate->heap()->EnableGrowthControl();
   isolate->set_init_callback_data(data);
   if (FLAG_print_class_table) {
@@ -185,9 +193,6 @@
 
 void Dart::ShutdownIsolate() {
   Isolate* isolate = Isolate::Current();
-  if (FLAG_trace_isolates) {
-    isolate->heap()->PrintSizes();
-  }
   void* callback_data = isolate->init_callback_data();
   isolate->Shutdown();
   delete isolate;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 5e50431..80938c0 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -793,9 +793,9 @@
   }
 
   char* chars = NULL;
-  intptr_t len = OS::SNPrint(NULL, 0, "%s/%s", script_uri, main) + 1;
+  intptr_t len = OS::SNPrint(NULL, 0, "%s$%s", script_uri, main) + 1;
   chars = reinterpret_cast<char*>(malloc(len));
-  OS::SNPrint(chars, len, "%s/%s", script_uri, main);
+  OS::SNPrint(chars, len, "%s$%s", script_uri, main);
   return chars;
 }
 
@@ -1908,10 +1908,12 @@
     const Instance& instance =
         Instance::Handle(isolate, GetListInstance(isolate, obj));
     if (!instance.IsNull()) {
-      String& name = String::Handle(isolate, Symbols::IndexToken());
-      const Function& function =
-          Function::Handle(isolate,
-                           Resolver::ResolveDynamic(instance, name, 2, 0));
+      const Function& function = Function::Handle(
+          isolate,
+          Resolver::ResolveDynamic(instance,
+                                   Symbols::IndexTokenHandle(),
+                                   2,
+                                   0));
       if (!function.IsNull()) {
         GrowableArray<const Object*> args(1);
         Integer& indexobj = Integer::Handle(isolate);
@@ -1960,10 +1962,12 @@
     const Instance& instance =
         Instance::Handle(isolate, GetListInstance(isolate, obj));
     if (!instance.IsNull()) {
-      String& name = String::Handle(isolate, Symbols::AssignIndexToken());
-      const Function& function =
-          Function::Handle(isolate,
-                           Resolver::ResolveDynamic(instance, name, 3, 0));
+      const Function& function = Function::Handle(
+          isolate,
+          Resolver::ResolveDynamic(instance,
+                                   Symbols::AssignIndexTokenHandle(),
+                                   3,
+                                   0));
       if (!function.IsNull()) {
         const Integer& index_obj =
             Integer::Handle(isolate, Integer::New(index));
@@ -2043,10 +2047,12 @@
     const Instance& instance =
         Instance::Handle(isolate, GetListInstance(isolate, obj));
     if (!instance.IsNull()) {
-      String& name = String::Handle(isolate, Symbols::IndexToken());
-      const Function& function =
-          Function::Handle(isolate,
-                           Resolver::ResolveDynamic(instance, name, 2, 0));
+      const Function& function = Function::Handle(
+          isolate,
+          Resolver::ResolveDynamic(instance,
+                                   Symbols::IndexTokenHandle(),
+                                   2,
+                                   0));
       if (!function.IsNull()) {
         Object& result = Object::Handle(isolate);
         Integer& intobj = Integer::Handle(isolate);
@@ -2132,10 +2138,12 @@
     const Instance& instance =
         Instance::Handle(isolate, GetListInstance(isolate, obj));
     if (!instance.IsNull()) {
-      String& name = String::Handle(isolate, Symbols::AssignIndexToken());
-      const Function& function =
-          Function::Handle(isolate,
-                           Resolver::ResolveDynamic(instance, name, 3, 0));
+      const Function& function = Function::Handle(
+          isolate,
+          Resolver::ResolveDynamic(instance,
+                                   Symbols::AssignIndexTokenHandle(),
+                                   3,
+                                   0));
       if (!function.IsNull()) {
         Integer& indexobj = Integer::Handle(isolate);
         Integer& valueobj = Integer::Handle(isolate);
@@ -2745,8 +2753,7 @@
     // Case 4.  Lookup the function with a . appended to find the
     // unnamed constructor.
     if (func.IsNull()) {
-      const String& dot = String::Handle(Symbols::Dot());
-      tmp_name = String::Concat(func_name, dot);
+      tmp_name = String::Concat(func_name, Symbols::DotHandle());
       func = cls.LookupFunction(tmp_name);
     }
   } else if (obj.IsLibrary()) {
@@ -3313,8 +3320,7 @@
   if (name_obj.IsNull()) {
     dot_name = Symbols::Dot();
   } else if (name_obj.IsString()) {
-    const String& dot = String::Handle(isolate, Symbols::Dot());
-    dot_name = String::Concat(dot, String::Cast(name_obj));
+    dot_name = String::Concat(Symbols::DotHandle(), String::Cast(name_obj));
   } else {
     RETURN_TYPE_ERROR(isolate, constructor_name, String);
   }
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 78fb68c..493af6c 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -106,7 +106,7 @@
   for (int i = 1; i < num_arguments; i++) {
     args.Add(arguments[i - 1]);
   }
-  // Now Call the invoke stub which will invoke the closure.
+  // Now call the invoke stub which will invoke the closure.
   invokestub entrypoint = reinterpret_cast<invokestub>(
       StubCode::InvokeDartCodeEntryPoint());
   ASSERT(context.isolate() == Isolate::Current());
@@ -223,8 +223,8 @@
   constructor_arguments.Add(&Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
   constructor_arguments.AddArray(arguments);
 
-  const String& period = String::Handle(Symbols::Dot());
-  String& constructor_name = String::Handle(String::Concat(class_name, period));
+  String& constructor_name = String::Handle(
+      String::Concat(class_name, Symbols::DotHandle()));
   Function& constructor =
       Function::Handle(cls.LookupConstructor(constructor_name));
   ASSERT(!constructor.IsNull());
@@ -265,7 +265,6 @@
 
 RawObject* DartLibraryCalls::Equals(const Instance& left,
                                     const Instance& right) {
-  const String& function_name = String::Handle(Symbols::EqualOperator());
   GrowableArray<const Object*> arguments;
   arguments.Add(&right);
   const int kNumArguments = 2;
@@ -273,7 +272,7 @@
   const Array& kNoArgumentNames = Array::Handle();
   const Function& function = Function::Handle(
       Resolver::ResolveDynamic(left,
-                               function_name,
+                               Symbols::EqualOperatorHandle(),
                                kNumArguments,
                                kNumNamedArguments));
   ASSERT(!function.IsNull());
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index f56af6a..432a376 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -9,6 +9,7 @@
 #include "vm/debugger.h"
 #include "vm/flags.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
 #include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
@@ -16,7 +17,10 @@
 namespace dart {
 
 DEFINE_FLAG(bool, print_stacktrace_at_throw, false,
-    "Prints a stack trace everytime a throw occurs.");
+            "Prints a stack trace everytime a throw occurs.");
+DEFINE_FLAG(bool, heap_profile_out_of_memory, false,
+            "Writes a heap profile on unhandled out-of-memory exceptions.");
+DECLARE_FLAG(bool, heap_profile_out_of_memory);
 
 
 const char* Exceptions::kCastErrorDstName = "type cast";
@@ -190,6 +194,12 @@
                            exception,
                            stacktrace);
   } else {
+    if (FLAG_heap_profile_out_of_memory) {
+      Isolate* isolate = Isolate::Current();
+      if (exception.raw() == isolate->object_store()->out_of_memory()) {
+        isolate->heap()->ProfileToFile("out-of-memory");
+      }
+    }
     // No dart exception handler found in this invocation sequence,
     // so we create an unhandled exception object and return to the
     // invocation stub so that it returns this unhandled exception
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index f48ac9e..f2aafe0 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1749,7 +1749,7 @@
 
   const String& function_name = String::Handle(function.name());
   const String& expected_function_name = String::Handle(
-      String::Concat(expected_class_name, String::Handle(Symbols::Dot())));
+      String::Concat(expected_class_name, Symbols::DotHandle()));
   return function_name.Equals(expected_function_name);
 }
 
@@ -2368,11 +2368,9 @@
   Function* super_function = NULL;
   if (node->IsSuperLoad()) {
     // Resolve the load indexed operator in the super class.
-    const String& index_operator_name =
-        String::ZoneHandle(Symbols::IndexToken());
     super_function = &Function::ZoneHandle(
           Resolver::ResolveDynamicAnyArgs(node->super_class(),
-                                          index_operator_name));
+                                          Symbols::IndexTokenHandle()));
     if (super_function->IsNull()) {
       // Could not resolve super operator. Generate call noSuchMethod() of the
       // super class instead.
@@ -2381,7 +2379,7 @@
       StaticCallInstr* call =
           BuildStaticNoSuchMethodCall(node->super_class(),
                                       node->array(),
-                                      index_operator_name,
+                                      Symbols::IndexTokenHandle(),
                                       arguments);
       ReturnDefinition(call);
       return;
@@ -2409,9 +2407,8 @@
   } else {
     // Generate dynamic call to index operator.
     const intptr_t checked_argument_count = 1;
-    const String& name = String::ZoneHandle(Symbols::IndexToken());
     InstanceCallInstr* load = new InstanceCallInstr(node->token_pos(),
-                                                    name,
+                                                    Symbols::IndexTokenHandle(),
                                                     Token::kINDEX,
                                                     arguments,
                                                     Array::ZoneHandle(),
@@ -2427,11 +2424,9 @@
   Function* super_function = NULL;
   if (node->IsSuperStore()) {
     // Resolve the store indexed operator in the super class.
-    const String& store_index_op_name =
-        String::ZoneHandle(Symbols::AssignIndexToken());
     super_function = &Function::ZoneHandle(
         Resolver::ResolveDynamicAnyArgs(node->super_class(),
-                                        store_index_op_name));
+                                        Symbols::AssignIndexTokenHandle()));
     if (super_function->IsNull()) {
       // Could not resolve super operator. Generate call noSuchMethod() of the
       // super class instead.
@@ -2449,7 +2444,7 @@
       StaticCallInstr* call =
           BuildStaticNoSuchMethodCall(node->super_class(),
                                       node->array(),
-                                      store_index_op_name,
+                                      Symbols::AssignIndexTokenHandle(),
                                       arguments);
       if (result_is_needed) {
         Do(call);
@@ -2809,7 +2804,13 @@
   ArgumentListNode* arguments = new ArgumentListNode(args_pos);
   // The first argument is the original method name.
   arguments->Add(new LiteralNode(args_pos, method_name));
-  // The second argument is an array containing the original method arguments.
+  // The second argument is the arguments descriptor of the original method.
+  const Array& args_descriptor =
+      Array::ZoneHandle(ArgumentsDescriptor::New(method_arguments->length(),
+                                                 method_arguments->names()));
+  arguments->Add(new LiteralNode(args_pos, args_descriptor));
+  // The third argument is an array containing the original method arguments,
+  // including the receiver.
   ArrayNode* args_array =
       new ArrayNode(args_pos, Type::ZoneHandle(Type::ArrayType()));
   for (intptr_t i = 0; i < method_arguments->length(); i++) {
@@ -2935,9 +2936,6 @@
                            initial_loop_depth);
   graph_entry_ = new GraphEntryInstr(normal_entry);
   EffectGraphVisitor for_effect(this, 0, initial_loop_depth);
-  if (InInliningContext()) {
-    exits_ = new ZoneGrowableArray<ReturnInstr*>();
-  }
   // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the
   // stack check on entry for leaf routines).
   Instruction* check = new CheckStackOverflowInstr(function.token_pos());
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index d259e97..da86242 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -534,24 +534,25 @@
                               argument_count, deopt_id, token_pos, locs);
     return;
   }
+
   if (is_optimizing()) {
-    // Megamorphic call requires one argument ICData.
-    ASSERT(ic_data.num_args_tested() == 1);
-    label_address = StubCode::MegamorphicCallEntryPoint();
-  } else {
-    switch (ic_data.num_args_tested()) {
-      case 1:
-        label_address = StubCode::OneArgCheckInlineCacheEntryPoint();
-        break;
-      case 2:
-        label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint();
-        break;
-      case 3:
-        label_address = StubCode::ThreeArgsCheckInlineCacheEntryPoint();
-        break;
-      default:
-        UNIMPLEMENTED();
-    }
+    EmitMegamorphicInstanceCall(ic_data, arguments_descriptor, argument_count,
+                                deopt_id, token_pos, locs);
+    return;
+  }
+
+  switch (ic_data.num_args_tested()) {
+    case 1:
+      label_address = StubCode::OneArgCheckInlineCacheEntryPoint();
+      break;
+    case 2:
+      label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint();
+      break;
+    case 3:
+      label_address = StubCode::ThreeArgsCheckInlineCacheEntryPoint();
+      break;
+    default:
+      UNIMPLEMENTED();
   }
   ExternalLabel target_label("InlineCache", label_address);
   EmitInstanceCall(&target_label, ic_data, arguments_descriptor, argument_count,
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 47f6ed3..9f4b9b3 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1098,6 +1098,73 @@
 }
 
 
+void FlowGraphCompiler::EmitMegamorphicInstanceCall(
+    const ICData& ic_data,
+    const Array& arguments_descriptor,
+    intptr_t argument_count,
+    intptr_t deopt_id,
+    intptr_t token_pos,
+    LocationSummary* locs) {
+  MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
+  const String& name = String::Handle(ic_data.target_name());
+  const MegamorphicCache& cache =
+      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  Label not_smi, load_cache;
+  __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
+  __ testl(EAX, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
+  __ movl(EAX, Immediate(Smi::RawValue(kSmiCid)));
+  __ jmp(&load_cache);
+
+  __ Bind(&not_smi);
+  __ LoadClassId(EAX, EAX);
+  __ SmiTag(EAX);
+
+  // EAX: class ID of the receiver (smi).
+  __ Bind(&load_cache);
+  __ LoadObject(EBX, cache);
+  __ movl(EDI, FieldAddress(EBX, MegamorphicCache::buckets_offset()));
+  __ movl(EBX, FieldAddress(EBX, MegamorphicCache::mask_offset()));
+  // EDI: cache buckets array.
+  // EBX: mask.
+  __ movl(ECX, EAX);
+
+  Label loop, update, call_target_function;
+  __ jmp(&loop);
+
+  __ Bind(&update);
+  __ addl(ECX, Immediate(Smi::RawValue(1)));
+  __ Bind(&loop);
+  __ andl(ECX, EBX);
+  const intptr_t base = Array::data_offset();
+  // ECX is smi tagged, but table entries are two words, so TIMES_4.
+  __ movl(EDX, FieldAddress(EDI, ECX, TIMES_4, base));
+
+  ASSERT(kIllegalCid == 0);
+  __ testl(EDX, EDX);
+  __ j(ZERO, &call_target_function, Assembler::kNearJump);
+  __ cmpl(EDX, EAX);
+  __ j(NOT_EQUAL, &update, Assembler::kNearJump);
+
+  __ Bind(&call_target_function);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ movl(EAX, FieldAddress(EDI, ECX, TIMES_4, base + kWordSize));
+  __ movl(EAX, FieldAddress(EAX, Function::code_offset()));
+  __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
+  __ LoadObject(ECX, ic_data);
+  __ LoadObject(EDX, arguments_descriptor);
+  __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
+  __ call(EAX);
+  AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
+  RecordSafepoint(locs);
+  AddDeoptIndexAtCall(deopt_id, token_pos);
+  __ Drop(argument_count);
+}
+
+
 void FlowGraphCompiler::EmitStaticCall(const Function& function,
                                        const Array& arguments_descriptor,
                                        intptr_t argument_count,
diff --git a/runtime/vm/flow_graph_compiler_ia32.h b/runtime/vm/flow_graph_compiler_ia32.h
index 4af53ad..f29351c 100644
--- a/runtime/vm/flow_graph_compiler_ia32.h
+++ b/runtime/vm/flow_graph_compiler_ia32.h
@@ -141,6 +141,13 @@
                         intptr_t token_pos,
                         LocationSummary* locs);
 
+  void EmitMegamorphicInstanceCall(const ICData& ic_data,
+                                   const Array& arguments_descriptor,
+                                   intptr_t argument_count,
+                                   intptr_t deopt_id,
+                                   intptr_t token_pos,
+                                   LocationSummary* locs);
+
   void EmitTestAndCall(const ICData& ic_data,
                        Register class_id_reg,
                        intptr_t arg_count,
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index ac94468..a998490 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1102,6 +1102,73 @@
 }
 
 
+void FlowGraphCompiler::EmitMegamorphicInstanceCall(
+    const ICData& ic_data,
+    const Array& arguments_descriptor,
+    intptr_t argument_count,
+    intptr_t deopt_id,
+    intptr_t token_pos,
+    LocationSummary* locs) {
+  MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
+  const String& name = String::Handle(ic_data.target_name());
+  const MegamorphicCache& cache =
+      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  Label not_smi, load_cache;
+  __ movq(RAX, Address(RSP, (argument_count - 1) * kWordSize));
+  __ testq(RAX, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
+  __ movq(RAX, Immediate(Smi::RawValue(kSmiCid)));
+  __ jmp(&load_cache);
+
+  __ Bind(&not_smi);
+  __ LoadClassId(RAX, RAX);
+  __ SmiTag(RAX);
+
+  // RAX: class ID of the receiver (smi).
+  __ Bind(&load_cache);
+  __ LoadObject(RBX, cache);
+  __ movq(RDI, FieldAddress(RBX, MegamorphicCache::buckets_offset()));
+  __ movq(RBX, FieldAddress(RBX, MegamorphicCache::mask_offset()));
+  // RDI: cache buckets array.
+  // RBX: mask.
+  __ movq(RCX, RAX);
+
+  Label loop, update, call_target_function;
+  __ jmp(&loop);
+
+  __ Bind(&update);
+  __ addq(RCX, Immediate(Smi::RawValue(1)));
+  __ Bind(&loop);
+  __ andq(RCX, RBX);
+  const intptr_t base = Array::data_offset();
+  // RCX is smi tagged, but table entries are two words, so TIMES_8.
+  __ movq(RDX, FieldAddress(RDI, RCX, TIMES_8, base));
+
+  ASSERT(kIllegalCid == 0);
+  __ testq(RDX, RDX);
+  __ j(ZERO, &call_target_function, Assembler::kNearJump);
+  __ cmpq(RDX, RAX);
+  __ j(NOT_EQUAL, &update, Assembler::kNearJump);
+
+  __ Bind(&call_target_function);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize));
+  __ movq(RAX, FieldAddress(RAX, Function::code_offset()));
+  __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
+  __ LoadObject(RBX, ic_data);
+  __ LoadObject(R10, arguments_descriptor);
+  __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
+  __ call(RAX);
+  AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
+  RecordSafepoint(locs);
+  AddDeoptIndexAtCall(deopt_id, token_pos);
+  __ Drop(argument_count);
+}
+
+
 void FlowGraphCompiler::EmitStaticCall(const Function& function,
                                        const Array& arguments_descriptor,
                                        intptr_t argument_count,
diff --git a/runtime/vm/flow_graph_compiler_x64.h b/runtime/vm/flow_graph_compiler_x64.h
index cb6c742..f62868b 100644
--- a/runtime/vm/flow_graph_compiler_x64.h
+++ b/runtime/vm/flow_graph_compiler_x64.h
@@ -141,6 +141,13 @@
                         intptr_t token_pos,
                         LocationSummary* locs);
 
+  void EmitMegamorphicInstanceCall(const ICData& ic_data,
+                                   const Array& arguments_descriptor,
+                                   intptr_t argument_count,
+                                   intptr_t deopt_id,
+                                   intptr_t token_pos,
+                                   LocationSummary* locs);
+
   void EmitTestAndCall(const ICData& ic_data,
                        Register class_id_reg,
                        intptr_t arg_count,
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 36a5d09..facc555 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -1669,6 +1669,13 @@
         known_smis_->Add(value_ssa_index);
         rollback_checks_.Add(value_ssa_index);
       }
+    } else if (instr->IsBranch()) {
+      for (intptr_t i = 0; i < instr->InputCount(); i++) {
+        Value* use = instr->InputAt(i);
+        if (known_smis_->Contains(use->definition()->ssa_temp_index())) {
+          use->set_reaching_cid(kSmiCid);
+        }
+      }
     }
   }
 
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index a512fd8..a4fe592 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -214,6 +214,7 @@
   HandlesBlock* scoped_blocks_;  // List of scoped handles.
 
   friend class HandleScope;
+  friend class Symbols;
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(Handles);
 };
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index d2f1615..79c335d 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -286,6 +286,26 @@
 }
 
 
+void Heap::ProfileToFile(const char* reason) const {
+  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+  ASSERT(file_open != NULL);
+  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+  ASSERT(file_write != NULL);
+  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+  ASSERT(file_close != NULL);
+  Isolate* isolate = Isolate::Current();
+  const char* format = "%s-%s.hprof";
+  intptr_t len = OS::SNPrint(NULL, 0, format, isolate->name(), reason);
+  char* filename = isolate->current_zone()->Alloc<char>(len + 1);
+  OS::SNPrint(filename, len + 1, format, isolate->name(), reason);
+  void* file = (*file_open)(filename);
+  if (file != NULL) {
+    Profile(file_write, file);
+    (*file_close)(file);
+  }
+}
+
+
 const char* Heap::GCReasonToString(GCReason gc_reason) {
   switch (gc_reason) {
     case kNewSpace:
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index ae47fea..c466642 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -158,6 +158,7 @@
 
   // Generates a profile of the current and VM isolate heaps.
   void Profile(Dart_FileWriteCallback callback, void* stream) const;
+  void ProfileToFile(const char* reason) const;
 
   static const char* GCReasonToString(GCReason gc_reason);
 
diff --git a/runtime/vm/heap_profiler.cc b/runtime/vm/heap_profiler.cc
index 48d24c7..86b6dfc 100644
--- a/runtime/vm/heap_profiler.cc
+++ b/runtime/vm/heap_profiler.cc
@@ -400,8 +400,17 @@
   record.WritePointer(raw_class);
   // stack trace serial number
   record.Write32(0);
-  ASSERT(raw_class->ptr()->name_ != String::null());
-  record.WritePointer(StringId(raw_class->ptr()->name_));
+  // class name string ID
+  if (raw_class->ptr()->name_ != String::null()) {
+    record.WritePointer(StringId(raw_class->ptr()->name_));
+  } else {
+    const char* format = "<an unnamed class with id %d>";
+    intptr_t len = OS::SNPrint(NULL, 0, format, raw_class->ptr()->id_);
+    char* str = new char[len + 1];
+    OS::SNPrint(str, len + 1, format, raw_class->ptr()->id_);
+    record.WritePointer(StringId(str));
+    delete[] str;
+  }
 }
 
 
@@ -600,8 +609,9 @@
         RawField* raw_field =
             reinterpret_cast<RawField*>(raw_array->ptr()->data()[i]);
         if (!Field::StaticBit::decode(raw_field->ptr()->kind_bits_)) {
-          intptr_t offset =
+          intptr_t offset_in_words =
               Smi::Value(reinterpret_cast<RawSmi*>(raw_field->ptr()->value_));
+          intptr_t offset = offset_in_words * kWordSize;
           RawObject* ptr = *reinterpret_cast<RawObject**>(base + offset);
           sub.WritePointer(ObjectId(ptr));
         }
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index efdcb30..3fd0394 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -1323,12 +1323,12 @@
 
 
 RawAbstractType* BinarySmiOpInstr::CompileType() const {
-  return (op_kind() == Token::kSHL) ? Type::IntType() : Type::SmiType();
+  return Type::SmiType();
 }
 
 
 intptr_t BinarySmiOpInstr::ResultCid() const {
-  return (op_kind() == Token::kSHL) ? kDynamicCid : kSmiCid;
+  return kSmiCid;
 }
 
 
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 997aac9..ccfa829 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -2058,7 +2058,7 @@
         arguments_(arguments),
         argument_names_(argument_names),
         checked_argument_count_(checked_argument_count) {
-    ASSERT(function_name.IsZoneHandle());
+    ASSERT(function_name.IsNotTemporaryScopedHandle());
     ASSERT(!arguments->is_empty());
     ASSERT(argument_names.IsZoneHandle());
     ASSERT(Token::IsBinaryOperator(token_kind) ||
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 8a1e32f..a7b2ac5 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -353,7 +353,6 @@
                                    deopt_id,
                                    token_pos);
   }
-  const String& operator_name = String::ZoneHandle(Symbols::EqualOperator());
   const int kNumberOfArguments = 2;
   const Array& kNoArgumentNames = Array::Handle();
   const int kNumArgumentsChecked = 2;
@@ -362,9 +361,9 @@
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   Label check_identity;
   __ cmpl(Address(ESP, 0 * kWordSize), raw_null);
-  __ j(EQUAL, &check_identity, Assembler::kNearJump);
+  __ j(EQUAL, &check_identity);
   __ cmpl(Address(ESP, 1 * kWordSize), raw_null);
-  __ j(EQUAL, &check_identity, Assembler::kNearJump);
+  __ j(EQUAL, &check_identity);
 
   ICData& equality_ic_data = ICData::ZoneHandle();
   if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
@@ -378,7 +377,7 @@
     }
   } else {
     equality_ic_data = ICData::New(compiler->parsed_function().function(),
-                                   operator_name,
+                                   Symbols::EqualOperatorHandle(),
                                    deopt_id,
                                    kNumArgumentsChecked);
   }
@@ -1748,6 +1747,7 @@
       : instruction_(instruction) { }
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
     compiler->SaveLiveRegisters(instruction_->locs());
     compiler->GenerateCallRuntime(instruction_->token_pos(),
@@ -2084,6 +2084,7 @@
       : instruction_(instruction) { }
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxDoubleSlowPath");
     __ Bind(entry_label());
     const Class& double_class = compiler->double_class();
     const Code& stub =
@@ -2560,6 +2561,7 @@
       : instruction_(instruction) { }
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxIntegerSlowPath");
     __ Bind(entry_label());
     const Class& mint_class =
         Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 51bcc51..d18c97d 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -354,7 +354,6 @@
                                    deopt_id,
                                    token_pos);
   }
-  const String& operator_name = String::ZoneHandle(Symbols::EqualOperator());
   const int kNumberOfArguments = 2;
   const Array& kNoArgumentNames = Array::Handle();
   const int kNumArgumentsChecked = 2;
@@ -363,9 +362,9 @@
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   Label check_identity;
   __ cmpq(Address(RSP, 0 * kWordSize), raw_null);
-  __ j(EQUAL, &check_identity, Assembler::kNearJump);
+  __ j(EQUAL, &check_identity);
   __ cmpq(Address(RSP, 1 * kWordSize), raw_null);
-  __ j(EQUAL, &check_identity, Assembler::kNearJump);
+  __ j(EQUAL, &check_identity);
 
   ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw());
   if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
@@ -379,7 +378,7 @@
     }
   } else {
     equality_ic_data = ICData::New(compiler->parsed_function().function(),
-                                   operator_name,
+                                   Symbols::EqualOperatorHandle(),
                                    deopt_id,
                                    kNumArgumentsChecked);
   }
@@ -1607,6 +1606,7 @@
       : instruction_(instruction) { }
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
     compiler->SaveLiveRegisters(instruction_->locs());
     compiler->GenerateCallRuntime(instruction_->token_pos(),
@@ -1968,6 +1968,7 @@
       : instruction_(instruction) { }
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxDoubleSlowPath");
     __ Bind(entry_label());
     const Class& double_class = compiler->double_class();
     const Code& stub =
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 6ea6661..5ac23bc 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -452,7 +452,9 @@
   if (FLAG_trace_isolates) {
     StackZone zone(this);
     HandleScope handle_scope(this);
-    OS::Print("Number of symbols added = %"Pd"\n", Symbols::Size(this));
+    heap()->PrintSizes();
+    megamorphic_cache_table()->PrintSizes();
+    Symbols::DumpStats();
     OS::Print("[-] Stopping isolate:\n"
               "\tisolate:    %s\n", name());
   }
@@ -483,6 +485,9 @@
   // Visit objects in the class table.
   class_table()->VisitObjectPointers(visitor);
 
+  // Visit objects in the megamorphic cache.
+  megamorphic_cache_table()->VisitObjectPointers(visitor);
+
   // Visit objects in per isolate stubs.
   StubCode::VisitObjectPointers(visitor);
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 6fb8623..bfbbaa8 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -7,10 +7,11 @@
 
 #include "include/dart_api.h"
 #include "platform/assert.h"
-#include "vm/class_table.h"
 #include "platform/thread.h"
 #include "vm/base_isolate.h"
+#include "vm/class_table.h"
 #include "vm/gc_callbacks.h"
+#include "vm/megamorphic_cache_table.h"
 #include "vm/store_buffer.h"
 #include "vm/timer.h"
 
@@ -114,6 +115,10 @@
     return OFFSET_OF(Isolate, class_table_);
   }
 
+  MegamorphicCacheTable* megamorphic_cache_table() {
+    return &megamorphic_cache_table_;
+  }
+
   Dart_MessageNotifyCallback message_notify_callback() const {
     return message_notify_callback_;
   }
@@ -343,6 +348,7 @@
   StoreBufferBlock store_buffer_block_;
   StoreBuffer store_buffer_;
   ClassTable class_table_;
+  MegamorphicCacheTable megamorphic_cache_table_;
   Dart_MessageNotifyCallback message_notify_callback_;
   char* name_;
   Dart_Port main_port_;
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
new file mode 100644
index 0000000..bec06e3
--- /dev/null
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -0,0 +1,99 @@
+// 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 "vm/megamorphic_cache_table.h"
+
+#include <stdlib.h>
+#include "vm/object.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+MegamorphicCacheTable::MegamorphicCacheTable()
+    : miss_handler_(NULL),
+      capacity_(0),
+      length_(0),
+      table_(NULL) {
+}
+
+
+MegamorphicCacheTable::~MegamorphicCacheTable() {
+  free(table_);
+}
+
+
+RawMegamorphicCache* MegamorphicCacheTable::Lookup(const String& name,
+                                                   const Array& descriptor) {
+  for (intptr_t i = 0; i < length_; ++i) {
+    if ((table_[i].name == name.raw()) &&
+        (table_[i].descriptor == descriptor.raw())) {
+      return table_[i].cache;
+    }
+  }
+
+  if (length_ == capacity_) {
+    capacity_ += kCapacityIncrement;
+    table_ =
+        reinterpret_cast<Entry*>(realloc(table_, capacity_ * sizeof(*table_)));
+  }
+
+  ASSERT(length_ < capacity_);
+  const MegamorphicCache& cache =
+      MegamorphicCache::Handle(MegamorphicCache::New());
+  Entry entry = { name.raw(), descriptor.raw(), cache.raw() };
+  table_[length_++] = entry;
+  return cache.raw();
+}
+
+
+void MegamorphicCacheTable::InitMissHandler() {
+  // The miss handler for a class ID not found in the table is invoked as a
+  // normal Dart function.
+  const Code& code =
+      Code::Handle(StubCode::Generate("_stub_MegamorphicMiss",
+                                      StubCode::GenerateMegamorphicMissStub));
+  const String& name = String::Handle(Symbols::New("megamorphic_miss"));
+  const Class& cls =
+      Class::Handle(Type::Handle(Type::Function()).type_class());
+  const Function& function =
+      Function::Handle(Function::New(name,
+                                     RawFunction::kRegularFunction,
+                                     false,  // Not static.
+                                     false,  // Not const.
+                                     false,  // Not abstract.
+                                     false,  // Not external.
+                                     cls,
+                                     0));  // No token position.
+  function.SetCode(code);
+  miss_handler_ = function.raw();
+}
+
+
+void MegamorphicCacheTable::VisitObjectPointers(ObjectPointerVisitor* v) {
+  ASSERT(v != NULL);
+  v->VisitPointer(reinterpret_cast<RawObject**>(&miss_handler_));
+  for (intptr_t i = 0; i < length_; ++i) {
+    v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].name));
+    v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].descriptor));
+    v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].cache));
+  }
+}
+
+
+void MegamorphicCacheTable::PrintSizes() {
+  StackZone zone(Isolate::Current());
+  intptr_t size = 0;
+  MegamorphicCache& cache = MegamorphicCache::Handle();
+  Array& buckets = Array::Handle();
+  for (intptr_t i = 0; i < length_; ++i) {
+    cache = table_[i].cache;
+    buckets = cache.buckets();
+    size += MegamorphicCache::InstanceSize();
+    size += Array::InstanceSize(buckets.Length());
+  }
+  OS::Print("%"Pd" megamorphic caches using %"Pd"KB.\n", length_, size / 1024);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/megamorphic_cache_table.h b/runtime/vm/megamorphic_cache_table.h
new file mode 100644
index 0000000..1cfd8c2
--- /dev/null
+++ b/runtime/vm/megamorphic_cache_table.h
@@ -0,0 +1,54 @@
+// 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 VM_MEGAMORPHIC_CACHE_TABLE_H_
+#define VM_MEGAMORPHIC_CACHE_TABLE_H_
+
+#include "vm/allocation.h"
+
+namespace dart {
+
+class Array;
+class Function;
+class ObjectPointerVisitor;
+class RawArray;
+class RawFunction;
+class RawMegamorphicCache;
+class RawString;
+class String;
+
+class MegamorphicCacheTable {
+ public:
+  MegamorphicCacheTable();
+  ~MegamorphicCacheTable();
+
+  RawFunction* miss_handler() const { return miss_handler_; }
+  void InitMissHandler();
+
+  RawMegamorphicCache* Lookup(const String& name, const Array& descriptor);
+
+  void VisitObjectPointers(ObjectPointerVisitor* visitor);
+
+  void PrintSizes();
+
+ private:
+  struct Entry {
+    RawString* name;
+    RawArray* descriptor;
+    RawMegamorphicCache* cache;
+  };
+
+  static const int kCapacityIncrement = 128;
+
+  RawFunction* miss_handler_;
+  intptr_t capacity_;
+  intptr_t length_;
+  Entry* table_;
+
+  DISALLOW_COPY_AND_ASSIGN(MegamorphicCacheTable);
+};
+
+}  // namespace dart
+
+#endif  // VM_MEGAMORPHIC_CACHE_TABLE_H_
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index aad7fb9..6a29b50 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -51,9 +51,9 @@
                                     NativeArguments* arguments)
 
 
-// Natives should throw an exception if an illegal argument is passed.
+// Natives should throw an exception if an illegal argument or null is passed.
 // type name = value.
-#define GET_NATIVE_ARGUMENT(type, name, value)                                 \
+#define GET_NON_NULL_NATIVE_ARGUMENT(type, name, value)                        \
   const Instance& __##name##_instance__ =                                      \
       Instance::CheckedHandle(isolate, value);                                 \
   if (!__##name##_instance__.Is##type()) {                                     \
@@ -64,6 +64,21 @@
   const type& name = type::Cast(__##name##_instance__);
 
 
+// Natives should throw an exception if an illegal argument is passed.
+// type name = value.
+#define GET_NATIVE_ARGUMENT(type, name, value)                                 \
+  const Instance& __##name##_instance__ =                                      \
+      Instance::CheckedHandle(isolate, value);                                 \
+  type& name = type::Handle(isolate);                                          \
+  if (!__##name##_instance__.IsNull()) {                                       \
+    if (!__##name##_instance__.Is##type()) {                                   \
+      GrowableArray<const Object*> __args__;                                   \
+      __args__.Add(&__##name##_instance__);                                    \
+      Exceptions::ThrowByType(Exceptions::kArgument, __args__);                \
+    }                                                                          \
+  }                                                                            \
+  name ^= value;
+
 
 // Helper class for resolving and handling native functions.
 class NativeEntry : public AllStatic {
diff --git a/runtime/vm/native_entry_test.cc b/runtime/vm/native_entry_test.cc
index 8c58b66..3ed8980 100644
--- a/runtime/vm/native_entry_test.cc
+++ b/runtime/vm/native_entry_test.cc
@@ -6,6 +6,7 @@
 
 #include "vm/assembler.h"
 #include "vm/code_patcher.h"
+#include "vm/dart_api_impl.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/stack_frame.h"
@@ -55,6 +56,38 @@
 }
 
 
+// Test for accepting null arguments in native function.
+// Arg0-4: 5 smis or null.
+// Result: a smi representing the sum of all non-null arguments.
+void TestNonNullSmiSum(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Isolate* isolate = Isolate::Current();
+  int64_t result = 0;
+  int arg_count = Dart_GetNativeArgumentCount(args);
+  // Test the lower level macro GET_NATIVE_ARGUMENT.
+  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  for (int i = 0; i < arg_count; i++) {
+    Dart_Handle arg = Dart_GetNativeArgument(args, i);
+    GET_NATIVE_ARGUMENT(Integer, argument, arguments->NativeArgAt(i));
+    EXPECT(argument.IsInteger());  // May be null.
+    EXPECT_EQ(Api::UnwrapHandle(arg), argument.raw());  // May be null.
+    int64_t arg_value = -1;
+    if (argument.IsNull()) {
+      EXPECT_ERROR(Dart_IntegerToInt64(arg, &arg_value),
+                   "Dart_IntegerToInt64 expects argument 'integer' "
+                   "to be non-null.");
+    } else {
+      EXPECT_VALID(Dart_IntegerToInt64(arg, &arg_value));
+      EXPECT_EQ(arg_value, argument.AsInt64Value());
+      // Ignoring overflow in the addition below.
+      result += arg_value;
+    }
+  }
+  Dart_SetReturnValue(args, Dart_NewInteger(result));
+  Dart_ExitScope();
+}
+
+
 // Test code patching.
 void TestStaticCallPatching(Dart_NativeArguments args) {
   Dart_EnterScope();
diff --git a/runtime/vm/native_entry_test.h b/runtime/vm/native_entry_test.h
index b00e155..0d4923a 100644
--- a/runtime/vm/native_entry_test.h
+++ b/runtime/vm/native_entry_test.h
@@ -11,6 +11,7 @@
 
 void TestSmiSub(Dart_NativeArguments args);
 void TestSmiSum(Dart_NativeArguments args);
+void TestNonNullSmiSum(Dart_NativeArguments args);
 void TestStaticCallPatching(Dart_NativeArguments args);
 
 }  // namespace dart
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 0dd23e8..934490f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -97,6 +97,8 @@
 RawClass* Object::context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::megamorphic_cache_class_ =
+    reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::subtypetestcache_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::api_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -107,6 +109,9 @@
 #undef RAW_NULL
 
 
+const double MegamorphicCache::kLoadFactor = 0.75;
+
+
 // Takes a vm internal name and makes it suitable for external user.
 //
 // Examples:
@@ -382,6 +387,9 @@
   cls = Class::New<ICData>();
   icdata_class_ = cls.raw();
 
+  cls = Class::New<MegamorphicCache>();
+  megamorphic_cache_class_ = cls.raw();
+
   cls = Class::New<SubtypeTestCache>();
   subtypetestcache_class_ = cls.raw();
 
@@ -457,6 +465,7 @@
   SET_CLASS_NAME(context, Context);
   SET_CLASS_NAME(context_scope, ContextScope);
   SET_CLASS_NAME(icdata, ICData);
+  SET_CLASS_NAME(megamorphic_cache, MegamorphicCache);
   SET_CLASS_NAME(subtypetestcache, SubtypeTestCache);
   SET_CLASS_NAME(api_error, ApiError);
   SET_CLASS_NAME(language_error, LanguageError);
@@ -1241,6 +1250,13 @@
 };
 
 
+bool Object::IsNotTemporaryScopedHandle() const {
+  return (IsZoneHandle() ||
+          Symbols::IsPredefinedHandle(reinterpret_cast<uword>(this)));
+}
+
+
+
 RawObject* Object::Clone(const Object& src, Heap::Space space) {
   const Class& cls = Class::Handle(src.clazz());
   intptr_t size = src.raw()->Size();
@@ -3386,10 +3402,9 @@
 
 bool Function::IsInlineable() const {
   // '==' call is handled specially.
-  const String& equality_name = String::Handle(Symbols::EqualOperator());
   return InlinableBit::decode(raw_ptr()->kind_tag_) &&
          HasCode() &&
-         name() != equality_name.raw();
+         name() != Symbols::EqualOperator();
 }
 
 
@@ -7777,6 +7792,120 @@
 }
 
 
+RawArray* MegamorphicCache::buckets() const {
+  return raw_ptr()->buckets_;
+}
+
+
+void MegamorphicCache::set_buckets(const Array& buckets) const {
+  StorePointer(&raw_ptr()->buckets_, buckets.raw());
+}
+
+
+// Class IDs in the table are smi-tagged, so we use a smi-tagged mask
+// and target class ID to avoid untagging (on each iteration of the
+// test loop) in generated code.
+intptr_t MegamorphicCache::mask() const {
+  return Smi::Value(raw_ptr()->mask_);
+}
+
+
+void MegamorphicCache::set_mask(intptr_t mask) const {
+  raw_ptr()->mask_ = Smi::New(mask);
+}
+
+
+intptr_t MegamorphicCache::filled_entry_count() const {
+  return raw_ptr()->filled_entry_count_;
+}
+
+
+void MegamorphicCache::set_filled_entry_count(intptr_t count) const {
+  raw_ptr()->filled_entry_count_ = count;
+}
+
+
+RawMegamorphicCache* MegamorphicCache::New() {
+  MegamorphicCache& result = MegamorphicCache::Handle();
+  { RawObject* raw = Object::Allocate(MegamorphicCache::kClassId,
+                                      MegamorphicCache::InstanceSize(),
+                                      Heap::kOld);
+    NoGCScope no_gc;
+    result ^= raw;
+  }
+  const intptr_t capacity = kInitialCapacity;
+  const Array& buckets = Array::Handle(Array::New(kEntryLength * capacity));
+  const Smi& illegal = Smi::Handle(Smi::New(kIllegalCid));
+  const Function& handler = Function::Handle(
+      Isolate::Current()->megamorphic_cache_table()->miss_handler());
+  for (intptr_t i = 0; i < capacity; ++i) {
+    SetEntry(buckets, i, illegal, handler);
+  }
+  result.set_buckets(buckets);
+  result.set_mask(capacity - 1);
+  result.set_filled_entry_count(0);
+  return result.raw();
+}
+
+
+void MegamorphicCache::EnsureCapacity() const {
+  intptr_t old_capacity = mask() + 1;
+  double load_limit = kLoadFactor * static_cast<double>(old_capacity);
+  if (static_cast<double>(filled_entry_count() + 1) > load_limit) {
+    const Array& old_buckets = Array::Handle(buckets());
+    intptr_t new_capacity = old_capacity * 2;
+    const Array& new_buckets =
+        Array::Handle(Array::New(kEntryLength * new_capacity));
+
+    Smi& class_id = Smi::Handle(Smi::New(kIllegalCid));
+    Function& target = Function::Handle(
+        Isolate::Current()->megamorphic_cache_table()->miss_handler());
+    for (intptr_t i = 0; i < new_capacity; ++i) {
+      SetEntry(new_buckets, i, class_id, target);
+    }
+    set_buckets(new_buckets);
+    set_mask(new_capacity - 1);
+    set_filled_entry_count(0);
+
+    // Rehash the valid entries.
+    for (intptr_t i = 0; i < old_capacity; ++i) {
+      class_id ^= GetClassId(old_buckets, i);
+      if (class_id.Value() != kIllegalCid) {
+        target ^= GetTargetFunction(old_buckets, i);
+        Insert(class_id, target);
+      }
+    }
+  }
+}
+
+
+void MegamorphicCache::Insert(const Smi& class_id,
+                              const Function& target) const {
+  ASSERT(static_cast<double>(filled_entry_count() + 1) <=
+         (kLoadFactor * static_cast<double>(mask() + 1)));
+  const Array& backing_array = Array::Handle(buckets());
+  intptr_t id_mask = mask();
+  intptr_t index = class_id.Value() & id_mask;
+  Smi& probe = Smi::Handle();
+  intptr_t i = index;
+  do {
+    probe ^= GetClassId(backing_array, i);
+    if (probe.Value() == kIllegalCid) {
+      SetEntry(backing_array, i, class_id, target);
+      set_filled_entry_count(filled_entry_count() + 1);
+      return;
+    }
+    i = (i + 1) & id_mask;
+  } while (i != index);
+  UNREACHABLE();
+}
+
+
+const char* MegamorphicCache::ToCString() const {
+  return "";
+}
+
+
 RawSubtypeTestCache* SubtypeTestCache::New() {
   ASSERT(Object::subtypetestcache_class() != Class::null());
   SubtypeTestCache& result = SubtypeTestCache::Handle();
@@ -11187,33 +11316,25 @@
 
 
 void GrowableObjectArray::Add(const Object& value, Heap::Space space) const {
-  Add(Isolate::Current(), value, space);
-}
-
-
-void GrowableObjectArray::Add(Isolate* isolate,
-                              const Object& value,
-                              Heap::Space space) const {
   ASSERT(!IsNull());
-  Array& contents = Array::Handle(isolate, data());
   if (Length() == Capacity()) {
     // TODO(Issue 2500): Need a better growth strategy.
     intptr_t new_capacity = (Capacity() == 0) ? 4 : Capacity() * 2;
     if (new_capacity <= Capacity()) {
       // Use the preallocated out of memory exception to avoid calling
       // into dart code or allocating any code.
+      Isolate* isolate = Isolate::Current();
       const Instance& exception =
           Instance::Handle(isolate->object_store()->out_of_memory());
       Exceptions::Throw(exception);
       UNREACHABLE();
     }
     Grow(new_capacity, space);
-    contents = data();
   }
   ASSERT(Length() < Capacity());
   intptr_t index = Length();
   SetLength(index + 1);
-  contents.SetAt(index, value);
+  SetAt(index, value);
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 515248a..367f64c 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -210,6 +210,8 @@
     return VMHandles::IsZoneHandle(reinterpret_cast<uword>(this));
   }
 
+  bool IsNotTemporaryScopedHandle() const;
+
   static RawObject* Clone(const Object& src, Heap::Space space = Heap::kNew);
 
   static Object& Handle(Isolate* isolate, RawObject* raw_ptr) {
@@ -294,6 +296,9 @@
   }
   static RawClass* unwind_error_class() { return unwind_error_class_; }
   static RawClass* icdata_class() { return icdata_class_; }
+  static RawClass* megamorphic_cache_class() {
+    return megamorphic_cache_class_;
+  }
   static RawClass* subtypetestcache_class() { return subtypetestcache_class_; }
 
   static RawError* Init(Isolate* isolate);
@@ -428,6 +433,7 @@
   static RawClass* context_class_;  // Class of the Context vm object.
   static RawClass* context_scope_class_;  // Class of ContextScope vm object.
   static RawClass* icdata_class_;  // Class of ICData.
+  static RawClass* megamorphic_cache_class_;  // Class of MegamorphiCache.
   static RawClass* subtypetestcache_class_;  // Class of SubtypeTestCache.
   static RawClass* api_error_class_;  // Class of ApiError.
   static RawClass* language_error_class_;  // Class of LanguageError.
@@ -2932,6 +2938,59 @@
 };
 
 
+class MegamorphicCache : public Object {
+ public:
+  static const int kInitialCapacity = 16;
+  static const double kLoadFactor;
+
+  RawArray* buckets() const;
+  void set_buckets(const Array& buckets) const;
+
+  intptr_t mask() const;
+  void set_mask(intptr_t mask) const;
+
+  intptr_t filled_entry_count() const;
+  void set_filled_entry_count(intptr_t num) const;
+
+  static intptr_t buckets_offset() {
+    return OFFSET_OF(RawMegamorphicCache, buckets_);
+  }
+  static intptr_t mask_offset() {
+    return OFFSET_OF(RawMegamorphicCache, mask_);
+  }
+
+  static RawMegamorphicCache* New();
+
+  void EnsureCapacity() const;
+
+  void Insert(const Smi& class_id, const Function& target) const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawMegamorphicCache));
+  }
+
+ private:
+  friend class Class;
+
+  enum {
+    kClassIdIndex,
+    kTargetFunctionIndex,
+    kEntryLength,
+  };
+
+  static inline void SetEntry(const Array& array,
+                              intptr_t index,
+                              const Smi& class_id,
+                              const Function& target);
+
+  static inline RawObject* GetClassId(const Array& array, intptr_t index);
+  static inline RawObject* GetTargetFunction(const Array& array,
+                                             intptr_t index);
+
+  HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache, Object);
+};
+
+
 class SubtypeTestCache : public Object {
  public:
   enum Entries {
@@ -4433,14 +4492,12 @@
   void SetAt(intptr_t index, const Object& value) const {
     ASSERT(!IsNull());
     ASSERT(index < Length());
-    const Array& arr = Array::Handle(data());
-    arr.SetAt(index, value);
+
+    // TODO(iposva): Add storing NoGCScope.
+    DataStorePointer(ObjectAddr(index), value.raw());
   }
 
   void Add(const Object& value, Heap::Space space = Heap::kNew) const;
-  void Add(Isolate* isolate,
-           const Object& value,
-           Heap::Space space = Heap::kNew) const;
 
   void Grow(intptr_t new_capacity, Heap::Space space = Heap::kNew) const;
   RawObject* RemoveLast() const;
@@ -4489,6 +4546,22 @@
     ASSERT((index >= 0) && (index < Length()));
     return &(DataArray()->data()[index]);
   }
+  bool DataContains(uword addr) const {
+    intptr_t data_size = data()->Size();
+    uword data_addr = RawObject::ToAddr(data());
+    return (addr >= data_addr) && (addr < (data_addr + data_size));
+  }
+  void DataStorePointer(RawObject** addr, RawObject* value) const {
+    // Ensure that the backing array object contains the addr.
+    ASSERT(DataContains(reinterpret_cast<uword>(addr)));
+    *addr = value;
+    // Filter stores based on source and target.
+    if (!value->IsHeapObject()) return;
+    if (value->IsNewObject() && data()->IsOldObject()) {
+      uword ptr = reinterpret_cast<uword>(addr);
+      Isolate::Current()->store_buffer()->AddPointer(ptr);
+    }
+  }
 
   static const int kDefaultInitialCapacity = 4;
 
@@ -6068,6 +6141,26 @@
   return true;
 }
 
+
+void MegamorphicCache::SetEntry(const Array& array,
+                                intptr_t index,
+                                const Smi& class_id,
+                                const Function& target) {
+  array.SetAt((index * kEntryLength) + kClassIdIndex, class_id);
+  array.SetAt((index * kEntryLength) + kTargetFunctionIndex, target);
+}
+
+
+RawObject* MegamorphicCache::GetClassId(const Array& array, intptr_t index) {
+  return array.At((index * kEntryLength) + kClassIdIndex);
+}
+
+
+RawObject* MegamorphicCache::GetTargetFunction(const Array& array,
+                                               intptr_t index) {
+  return array.At((index * kEntryLength) + kTargetFunctionIndex);
+}
+
 }  // namespace dart
 
 #endif  // VM_OBJECT_H_
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 8dc3234..397ccc1 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -435,7 +435,7 @@
   }
 
   void AddFinalParameter(intptr_t name_pos,
-                         String* name,
+                         const String* name,
                          const AbstractType* type) {
     this->num_fixed_parameters++;
     ParamDesc param;
@@ -449,7 +449,7 @@
   void AddReceiver(const Type* receiver_type) {
     ASSERT(this->parameters->is_empty());
     AddFinalParameter(receiver_type->token_pos(),
-                      &String::ZoneHandle(Symbols::This()),
+                      &Symbols::ThisHandle(),
                       receiver_type);
   }
 
@@ -1338,10 +1338,16 @@
   ArgumentListNode* arguments = new ArgumentListNode(args_pos);
   // The first argument is the original function name.
   arguments->Add(new LiteralNode(args_pos, function_name));
-  // The second argument is an array containing the original function arguments.
+  // The second argument is the arguments descriptor of the original function.
+  const Array& args_descriptor =
+      Array::ZoneHandle(ArgumentsDescriptor::New(function_args.length(),
+                                                 function_args.names()));
+  arguments->Add(new LiteralNode(args_pos, args_descriptor));
+  // The third argument is an array containing the original function arguments,
+  // including the receiver.
   ArrayNode* args_array = new ArrayNode(
       args_pos, Type::ZoneHandle(Type::ArrayType()));
-  for (intptr_t i = 1; i < function_args.length(); i++) {
+  for (intptr_t i = 0; i < function_args.length(); i++) {
     args_array->AddElement(function_args.NodeAt(i));
   }
   arguments->Add(args_array);
@@ -1589,8 +1595,7 @@
     return;
   }
   String& ctor_name = String::Handle(super_class.Name());
-  String& ctor_suffix = String::Handle(Symbols::Dot());
-  ctor_name = String::Concat(ctor_name, ctor_suffix);
+  ctor_name = String::Concat(ctor_name, Symbols::DotHandle());
   ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
   // Implicit 'this' parameter is the first argument.
   AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver);
@@ -1630,13 +1635,12 @@
   const Class& super_class = Class::Handle(cls.SuperClass());
   ASSERT(!super_class.IsNull());
   String& ctor_name = String::Handle(super_class.Name());
-  String& ctor_suffix = String::Handle(Symbols::Dot());
+  ctor_name = String::Concat(ctor_name, Symbols::DotHandle());
   if (CurrentToken() == Token::kPERIOD) {
     ConsumeToken();
-    ctor_suffix = String::Concat(
-        ctor_suffix, *ExpectIdentifier("constructor name expected"));
+    ctor_name = String::Concat(ctor_name,
+                               *ExpectIdentifier("constructor name expected"));
   }
-  ctor_name = String::Concat(ctor_name, ctor_suffix);
   if (CurrentToken() != Token::kLPAREN) {
     ErrorMsg("parameter list expected");
   }
@@ -1849,14 +1853,13 @@
   const intptr_t call_pos = TokenPos();
   ConsumeToken();
   String& ctor_name = String::Handle(cls.Name());
-  String& ctor_suffix = String::Handle(Symbols::Dot());
 
+  ctor_name = String::Concat(ctor_name, Symbols::DotHandle());
   if (CurrentToken() == Token::kPERIOD) {
     ConsumeToken();
-    ctor_suffix = String::Concat(
-        ctor_suffix, *ExpectIdentifier("constructor name expected"));
+    ctor_name = String::Concat(ctor_name,
+                               *ExpectIdentifier("constructor name expected"));
   }
-  ctor_name = String::Concat(ctor_name, ctor_suffix);
   if (CurrentToken() != Token::kLPAREN) {
     ErrorMsg("parameter list expected");
   }
@@ -1900,7 +1903,7 @@
   const Class& cls = Class::Handle(func.Owner());
   LocalVariable* receiver = new LocalVariable(
       ctor_pos,
-      String::ZoneHandle(Symbols::This()),
+      Symbols::ThisHandle(),
       Type::ZoneHandle(Type::DynamicType()));
   current_block_->scope->AddVariable(receiver);
 
@@ -2541,8 +2544,7 @@
       ConsumeToken();  // Colon.
       ExpectToken(Token::kTHIS);
       String& redir_name = String::ZoneHandle(
-          String::Concat(members->class_name(),
-                         String::Handle(Symbols::Dot())));
+          String::Concat(members->class_name(), Symbols::DotHandle()));
       if (CurrentToken() == Token::kPERIOD) {
         ConsumeToken();
         redir_name = String::Concat(redir_name,
@@ -2948,14 +2950,13 @@
     }
     // We must be dealing with a constructor or named constructor.
     member.kind = RawFunction::kConstructor;
-    String& ctor_suffix = String::ZoneHandle(Symbols::Dot());
+    *member.name = String::Concat(*member.name, Symbols::DotHandle());
     if (CurrentToken() == Token::kPERIOD) {
       // Named constructor.
       ConsumeToken();
       member.constructor_name = ExpectIdentifier("identifier expected");
-      ctor_suffix = String::Concat(ctor_suffix, *member.constructor_name);
+      *member.name = String::Concat(*member.name, *member.constructor_name);
     }
-    *member.name = String::Concat(*member.name, ctor_suffix);
     // Ensure that names are symbols.
     *member.name = Symbols::New(*member.name);
     if (member.type == NULL) {
@@ -3188,7 +3189,7 @@
   // The implicit constructor is unnamed, has no explicit parameter,
   // and contains a supercall in the initializer list.
   String& ctor_name = String::ZoneHandle(
-    String::Concat(class_desc->class_name(), String::Handle(Symbols::Dot())));
+    String::Concat(class_desc->class_name(), Symbols::DotHandle()));
   ctor_name = Symbols::New(ctor_name);
   // The token position for the implicit constructor is the 'class'
   // keyword of the constructor's class.
@@ -4075,10 +4076,9 @@
   ConsumeToken();
   String& lib_name = *ExpectIdentifier("library name expected");
   if (CurrentToken() == Token::kPERIOD) {
-    const String& dot = String::Handle(Symbols::Dot());
     while (CurrentToken() == Token::kPERIOD) {
       ConsumeToken();
-      lib_name = String::Concat(lib_name, dot);
+      lib_name = String::Concat(lib_name, Symbols::DotHandle());
       lib_name = String::Concat(lib_name,
           *ExpectIdentifier("malformed library name"));
     }
@@ -4538,8 +4538,7 @@
 
 LocalVariable* Parser::LookupReceiver(LocalScope* from_scope, bool test_only) {
   ASSERT(!current_function().is_static());
-  const String& this_name = String::Handle(Symbols::This());
-  return from_scope->LookupVariable(this_name, test_only);
+  return from_scope->LookupVariable(Symbols::ThisHandle(), test_only);
 }
 
 
@@ -7697,7 +7696,7 @@
   if (current_block_ == NULL) {
     return false;
   }
-  if (ident.Equals(String::Handle(Symbols::This()))) {
+  if (ident.Equals(Symbols::ThisHandle())) {
     // 'this' is not a formal parameter.
     return false;
   }
@@ -8876,9 +8875,8 @@
   // for class 'A' is labeled 'A.C', and the static function implementing the
   // unnamed constructor for class 'A' is labeled 'A.'.
   // This convention prevents users from explicitly calling constructors.
-  const String& period = String::Handle(Symbols::Dot());
   String& constructor_name =
-      String::Handle(String::Concat(type_class_name, period));
+      String::Handle(String::Concat(type_class_name, Symbols::DotHandle()));
   if (named_constructor != NULL) {
     constructor_name = String::Concat(constructor_name, *named_constructor);
   }
@@ -9313,8 +9311,7 @@
     }
     ASSERT(primary != NULL);
   } else if (CurrentToken() == Token::kTHIS) {
-    const String& this_name = String::Handle(Symbols::This());
-    LocalVariable* local = LookupLocalScope(this_name);
+    LocalVariable* local = LookupLocalScope(Symbols::ThisHandle());
     if (local == NULL) {
       ErrorMsg("receiver 'this' is not in scope");
     }
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index bdb23a3..06362bb 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -552,6 +552,14 @@
 }
 
 
+intptr_t RawMegamorphicCache::VisitMegamorphicCachePointers(
+    RawMegamorphicCache* raw_obj,
+    ObjectPointerVisitor* visitor) {
+  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+  return MegamorphicCache::InstanceSize();
+}
+
+
 intptr_t RawSubtypeTestCache::VisitSubtypeTestCachePointers(
     RawSubtypeTestCache* raw_obj, ObjectPointerVisitor* visitor) {
   // Make sure that we got here with the tagged pointer as this.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5ac48ec..bf5164e 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -40,6 +40,7 @@
   V(Context)                                                                   \
   V(ContextScope)                                                              \
   V(ICData)                                                                    \
+  V(MegamorphicCache)                                                          \
   V(SubtypeTestCache)                                                          \
   V(Error)                                                                     \
     V(ApiError)                                                                \
@@ -936,6 +937,22 @@
 };
 
 
+class RawMegamorphicCache : public RawObject {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache);
+
+  RawObject** from() {
+    return reinterpret_cast<RawObject**>(&ptr()->buckets_);
+  }
+  RawArray* buckets_;
+  RawSmi* mask_;
+  RawObject** to() {
+    return reinterpret_cast<RawObject**>(&ptr()->mask_);
+  }
+
+  intptr_t filled_entry_count_;
+};
+
+
 class RawSubtypeTestCache : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache);
   RawArray* cache_;
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 0c4c92b..fd891d4 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1251,6 +1251,22 @@
 }
 
 
+RawMegamorphicCache* MegamorphicCache::ReadFrom(SnapshotReader* reader,
+                                                intptr_t object_id,
+                                                intptr_t tags,
+                                                Snapshot::Kind kind) {
+  UNREACHABLE();
+  return NULL;
+}
+
+
+void RawMegamorphicCache::WriteTo(SnapshotWriter* writer,
+                                  intptr_t object_id,
+                                  Snapshot::Kind kind) {
+  UNREACHABLE();
+}
+
+
 RawSubtypeTestCache* SubtypeTestCache::ReadFrom(SnapshotReader* reader,
                                                 intptr_t object_id,
                                                 intptr_t tags,
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index 588587c..ccc6a3b 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -525,9 +525,8 @@
       ContextScope::Handle(ContextScope::New(kNumCapturedVars));
 
   // Create a descriptor for 'this' variable.
-  const String& name = String::Handle(Symbols::This());
   context_scope.SetTokenIndexAt(0, func.token_pos());
-  context_scope.SetNameAt(0, name);
+  context_scope.SetNameAt(0, Symbols::ThisHandle());
   context_scope.SetIsFinalAt(0, true);
   context_scope.SetIsConstAt(0, false);
   const AbstractType& type = AbstractType::Handle(func.ParameterTypeAt(0));
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 48ed808..da0fe25 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -159,6 +159,8 @@
   static const intptr_t kNoInstantiator = 0;
 
  private:
+  friend class MegamorphicCacheTable;
+
   static const intptr_t kStubCodeSize = 4 * KB;
 
 #define STUB_CODE_GENERATE(name)                                               \
@@ -184,6 +186,7 @@
   static RawCode* Generate(const char* name,
                            void (*GenerateStub)(Assembler* assembler));
 
+  static void GenerateMegamorphicMissStub(Assembler* assembler);
   static void GenerateAllocationStubForClass(Assembler* assembler,
                                              const Class& cls);
   static void GenerateAllocationStubForClosure(Assembler* assembler,
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 46a45b5..5b3ae64 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -348,8 +348,7 @@
   __ pushl(EBX);  // Closure object.
   __ pushl(EDX);  // Arguments descriptor.
   __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  __ SmiUntag(EDI);
-  __ subl(EDI, Immediate(1));  // Arguments array length, minus the receiver.
+  __ SmiUntag(EDI);  // Arguments array length, including the original receiver.
   PushArgumentsArray(assembler, (kWordSize * 6));
   // Stack layout explaining "(kWordSize * 6)" offset.
   // TOS + 0: Argument array.
@@ -375,7 +374,7 @@
 
   __ Bind(&function_not_found);
   // The target function was not found, so invoke method
-  // "void noSuchMethod(function_name, args_array)".
+  // "dynamic noSuchMethod(InvocationMirror invocation)".
   //   EAX: receiver.
   //   ECX: ic-data.
   //   EDX: arguments descriptor array.
@@ -385,8 +384,7 @@
   __ pushl(ECX);  // IC-data.
   __ pushl(EDX);  // Arguments descriptor array.
   __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  __ SmiUntag(EDI);
-  __ subl(EDI, Immediate(1));  // Arguments array length, minus the receiver.
+  __ SmiUntag(EDI);  // Arguments array length, including the original receiver.
   // See stack layout below explaining "wordSize * 7" offset.
   PushArgumentsArray(assembler, (kWordSize * 7));
 
@@ -533,6 +531,44 @@
 }
 
 
+void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
+  AssemblerMacros::EnterStubFrame(assembler);
+  // Load the receiver into EAX.  The argument count in the arguments
+  // descriptor in EDX is a smi.
+  __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
+  // Two words (return addres, saved fp) in the stack above the last argument.
+  __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize));
+  // Preserve IC data and arguments descriptor.
+  __ pushl(ECX);
+  __ pushl(EDX);
+
+  const Immediate raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Instructions::null()));
+  __ pushl(raw_null);  // Space for the result of the runtime call.
+  __ pushl(EAX);  // Pass receiver.
+  __ pushl(ECX);  // Pass IC data.
+  __ pushl(EDX);  // Pass rguments descriptor.
+  __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry);
+  // Discard arguments.
+  __ popl(EAX);
+  __ popl(EAX);
+  __ popl(EAX);
+  __ popl(EAX);  // Return value from the runtime call (instructions).
+  __ popl(EDX);  // Restore arguments descriptor.
+  __ popl(ECX);  // Restore IC data.
+  __ LeaveFrame();
+
+  Label lookup;
+  __ cmpl(EAX, raw_null);
+  __ j(EQUAL, &lookup, Assembler::kNearJump);
+  __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
+  __ jmp(EAX);
+
+  __ Bind(&lookup);
+  __ jmp(&StubCode::InstanceFunctionLookupLabel());
+}
+
+
 // Called for inline allocation of arrays.
 // Input parameters:
 //   EDX : Array length as Smi.
@@ -739,8 +775,10 @@
   __ jmp(ECX);
 
   __ Bind(&not_closure);
-  // Call runtime to report that a closure call was attempted on a non-closure
-  // object, passing the non-closure object and its arguments array.
+  // Call runtime to attempt to resolve and invoke a call method on a
+  // non-closure object, passing the non-closure object and its arguments array,
+  // returning here.
+  // If no call method exists, throw a NoSuchMethodError.
   // EDI: non-closure object.
   // EDX: arguments descriptor array.
 
@@ -750,24 +788,33 @@
 
   __ pushl(raw_null);  // Setup space on stack for result from error reporting.
   __ pushl(EDI);  // Non-closure object.
+  __ pushl(EDX);  // Arguments descriptor.
   // Load num_args.
   __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  __ SmiUntag(EDI);
-  __ subl(EDI, Immediate(1));  // Arguments array length, minus the closure.
-  // See stack layout below explaining "wordSize * 5" offset.
-  PushArgumentsArray(assembler, (kWordSize * 5));
+  __ SmiUntag(EDI);  // Arguments array length, including the non-closure.
+  // See stack layout below explaining "wordSize * 6" offset.
+  PushArgumentsArray(assembler, (kWordSize * 6));
 
   // Stack:
   // TOS + 0: Argument array.
-  // TOS + 1: Non-closure object.
-  // TOS + 2: Place for result from reporting the error.
-  // TOS + 3: PC marker => RawInstruction object.
-  // TOS + 4: Saved EBP of previous frame. <== EBP
-  // TOS + 5: Dart code return address
-  // TOS + 6: Last argument of caller.
+  // TOS + 1: Arguments descriptor array.
+  // TOS + 2: Non-closure object.
+  // TOS + 3: Place for result from the call.
+  // TOS + 4: PC marker => RawInstruction object.
+  // TOS + 5: Saved EBP of previous frame. <== EBP
+  // TOS + 6: Dart code return address
+  // TOS + 7: Last argument of caller.
   // ....
-  __ CallRuntime(kReportObjectNotClosureRuntimeEntry);
-  __ Stop("runtime call throws an exception");
+  __ CallRuntime(kInvokeNonClosureRuntimeEntry);
+  // Remove arguments.
+  __ popl(EAX);
+  __ popl(EAX);
+  __ popl(EAX);
+  __ popl(EAX);  // Get result into EAX.
+
+  // Remove the stub frame as we are about to return.
+  __ LeaveFrame();
+  __ ret();
 }
 
 
@@ -1407,14 +1454,7 @@
 // Uses EAX, EBX, EDI as temporary registers.
 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
   // The target function was not found, so invoke method
-  // "void noSuchMethod(function_name, Array arguments)".
-  // TODO(regis): For now, we simply pass the actual arguments, both positional
-  // and named, as the argument array. This is not correct if out-of-order
-  // named arguments were passed.
-  // The signature of the "noSuchMethod" method has to change from
-  // noSuchMethod(String name, Array arguments) to something like
-  // noSuchMethod(InvocationMirror call).
-  // Also, the class NoSuchMethodError has to be modified accordingly.
+  // "dynamic noSuchMethod(InvocationMirror invocation)".
   const Immediate raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
@@ -1429,7 +1469,7 @@
   __ pushl(EAX);  // Receiver.
   __ pushl(ECX);  // IC data array.
   __ pushl(EDX);  // Arguments descriptor array.
-  __ subl(EDI, Immediate(1));  // Arguments array length, minus the receiver.
+  // EDI: Arguments array length, including the receiver.
   // See stack layout below explaining "wordSize * 10" offset.
   PushArgumentsArray(assembler, (kWordSize * 10));
 
@@ -2069,13 +2109,12 @@
   __ Bind(&update_ic_data);
 
   // ECX: ICData
-  const String& equal_name = String::ZoneHandle(Symbols::EqualOperator());
   __ movl(EAX, Address(ESP, 1 * kWordSize));
   __ movl(EDI, Address(ESP, 2 * kWordSize));
   AssemblerMacros::EnterStubFrame(assembler);
   __ pushl(EDI);  // arg 0
   __ pushl(EAX);  // arg 1
-  __ PushObject(equal_name);  // Target's name.
+  __ PushObject(Symbols::EqualOperatorHandle());  // Target's name.
   __ pushl(ECX);  // ICData
   __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry);
   __ Drop(4);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index a6ca462..24116c8 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -343,8 +343,7 @@
   __ pushq(RCX);  // Closure object.
   __ pushq(R10);  // Arguments descriptor.
   __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ SmiUntag(R13);
-  __ subq(R13, Immediate(1));  // Arguments array length, minus the receiver.
+  __ SmiUntag(R13);  // Arguments array length, including the original receiver.
   PushArgumentsArray(assembler, (kWordSize * 6));
   // Stack layout explaining "(kWordSize * 6)" offset.
   // TOS + 0: Argument array.
@@ -370,7 +369,7 @@
 
   __ Bind(&function_not_found);
   // The target function was not found, so invoke method
-  // "void noSuchMethod(function_name, args_array)".
+  // "dynamic noSuchMethod(InvocationMirror invocation)".
   //   RAX: receiver.
   //   RBX: ic-data.
   //   R10: arguments descriptor array.
@@ -380,8 +379,7 @@
   __ pushq(RBX);  // IC-data array.
   __ pushq(R10);  // Arguments descriptor array.
   __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ SmiUntag(R13);
-  __ subq(R13, Immediate(1));  // Arguments array length, minus the receiver.
+  __ SmiUntag(R13);  // Arguments array length, including the original receiver.
   // See stack layout below explaining "wordSize * 7" offset.
   PushArgumentsArray(assembler, (kWordSize * 7));
 
@@ -529,6 +527,44 @@
 }
 
 
+void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
+  AssemblerMacros::EnterStubFrame(assembler);
+  // Load the receiver into RAX.  The argument count in the arguments
+  // descriptor in R10 is a smi.
+  __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
+  // Two words (return addres, saved fp) in the stack above the last argument.
+  __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize));
+  // Preserve IC data and arguments descriptor.
+  __ pushq(RBX);
+  __ pushq(R10);
+
+  const Immediate raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Instructions::null()));
+  __ pushq(raw_null);  // Space for the result of the runtime call.
+  __ pushq(RAX);  // Receiver.
+  __ pushq(RBX);  // IC data.
+  __ pushq(R10);  // Arguments descriptor.
+  __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry);
+  // Discard arguments.
+  __ popq(RAX);
+  __ popq(RAX);
+  __ popq(RAX);
+  __ popq(RAX);  // Return value from the runtime call (instructions).
+  __ popq(R10);  // Restore arguments descriptor.
+  __ popq(RBX);  // Restore IC data.
+  __ LeaveFrame();
+
+  Label lookup;
+  __ cmpq(RAX, raw_null);
+  __ j(EQUAL, &lookup, Assembler::kNearJump);
+  __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
+  __ jmp(RAX);
+
+  __ Bind(&lookup);
+  __ jmp(&StubCode::InstanceFunctionLookupLabel());
+}
+
+
 // Called for inline allocation of arrays.
 // Input parameters:
 //   R10 : Array length as Smi.
@@ -623,6 +659,7 @@
     // Initialize all array elements to raw_null.
     // RAX: new object start as a tagged pointer.
     // R12: new object end address.
+    // R10: Array length as Smi.
     __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
     // RBX: iterator which initially points to the start of the variable
     // data area to be initialized.
@@ -631,6 +668,7 @@
     __ Bind(&init_loop);
     __ cmpq(RBX, R12);
     __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
+    // TODO(cshapiro): StoreIntoObjectNoBarrier
     __ movq(Address(RBX, 0), raw_null);
     __ addq(RBX, Immediate(kWordSize));
     __ jmp(&init_loop, Assembler::kNearJump);
@@ -645,6 +683,8 @@
   // Unable to allocate the array using the fast inline code, just call
   // into the runtime.
   __ Bind(&slow_case);
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
   AssemblerMacros::EnterStubFrame(assembler);
   __ pushq(raw_null);  // Setup space on stack for return value.
   __ pushq(R10);  // Array length as Smi.
@@ -724,8 +764,10 @@
   __ jmp(RBX);
 
   __ Bind(&not_closure);
-  // Call runtime to report that a closure call was attempted on a non-closure
-  // object, passing the non-closure object and its arguments array.
+  // Call runtime to attempt to resolve and invoke a call method on a
+  // non-closure object, passing the non-closure object and its arguments array,
+  // returning here.
+  // If no call method exists, throw a NoSuchMethodError.
   // R13: non-closure object.
   // R10: arguments descriptor array.
 
@@ -733,26 +775,35 @@
   // calling into the runtime.
   AssemblerMacros::EnterStubFrame(assembler);
 
-  __ pushq(raw_null);  // Setup space on stack for result from error reporting.
+  __ pushq(raw_null);  // Setup space on stack for result from call.
   __ pushq(R13);  // Non-closure object.
+  __ pushq(R10);  // Arguments descriptor.
   // Load num_args.
   __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ SmiUntag(R13);
-  __ subq(R13, Immediate(1));  // Arguments array length, minus the closure.
-  // See stack layout below explaining "wordSize * 5" offset.
-  PushArgumentsArray(assembler, (kWordSize * 5));
+  __ SmiUntag(R13);  // Arguments array length, including the non-closure.
+  // See stack layout below explaining "wordSize * 6" offset.
+  PushArgumentsArray(assembler, (kWordSize * 6));
 
   // Stack:
   // TOS + 0: Argument array.
-  // TOS + 1: Non-closure object.
-  // TOS + 2: Place for result from reporting the error.
-  // TOS + 3: PC marker => RawInstruction object.
-  // TOS + 4: Saved RBP of previous frame. <== RBP
-  // TOS + 5: Dart code return address
-  // TOS + 6: Last argument of caller.
+  // TOS + 1: Arguments descriptor array.
+  // TOS + 2: Non-closure object.
+  // TOS + 3: Place for result from the call.
+  // TOS + 4: PC marker => RawInstruction object.
+  // TOS + 5: Saved RBP of previous frame. <== RBP
+  // TOS + 6: Dart code return address
+  // TOS + 7: Last argument of caller.
   // ....
-  __ CallRuntime(kReportObjectNotClosureRuntimeEntry);
-  __ Stop("runtime call throws an exception");
+  __ CallRuntime(kInvokeNonClosureRuntimeEntry);
+  // Remove arguments.
+  __ popq(RAX);
+  __ popq(RAX);
+  __ popq(RAX);
+  __ popq(RAX);  // Get result into RAX.
+
+  // Remove the stub frame as we are about to return.
+  __ LeaveFrame();
+  __ ret();
 }
 
 
@@ -1390,14 +1441,7 @@
 //   R10 : arguments descriptor array.
 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
   // The target function was not found, so invoke method
-  // "void noSuchMethod(function_name, Array arguments)".
-  // TODO(regis): For now, we simply pass the actual arguments, both positional
-  // and named, as the argument array. This is not correct if out-of-order
-  // named arguments were passed.
-  // The signature of the "noSuchMethod" method has to change from
-  // noSuchMethod(String name, Array arguments) to something like
-  // noSuchMethod(InvocationMirror call).
-  // Also, the class NoSuchMethodError has to be modified accordingly.
+  // "dynamic noSuchMethod(InvocationMirror invocation)".
   const Immediate raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
@@ -1411,7 +1455,7 @@
   __ pushq(RAX);  // Receiver.
   __ pushq(RBX);  // IC data array.
   __ pushq(R10);  // Arguments descriptor array.
-  __ subq(R13, Immediate(1));  // Arguments array length, minus the receiver.
+  // R13: Arguments array length, including the receiver.
   // See stack layout below explaining "wordSize * 10" offset.
   PushArgumentsArray(assembler, (kWordSize * 10));
 
@@ -2031,13 +2075,12 @@
   __ Bind(&update_ic_data);
 
   // RCX: ICData
-  const String& equal_name = String::ZoneHandle(Symbols::New("=="));
   __ movq(RAX, Address(RSP, 1 * kWordSize));
   __ movq(R13, Address(RSP, 2 * kWordSize));
   AssemblerMacros::EnterStubFrame(assembler);
   __ pushq(R13);  // arg 0
   __ pushq(RAX);  // arg 1
-  __ PushObject(equal_name);  // Target's name.
+  __ PushObject(Symbols::EqualOperatorHandle());  // Target's name.
   __ pushq(RBX);  // ICData
   __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry);
   __ Drop(4);
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 125f072..9813d88 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -4,6 +4,8 @@
 
 #include "vm/symbols.h"
 
+#include "vm/handles.h"
+#include "vm/handles_impl.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
@@ -16,6 +18,13 @@
 
 RawString* Symbols::predefined_[Symbols::kMaxId];
 
+Symbols::ReadOnlyHandles* Symbols::predefined_handles_ = NULL;
+
+#define DEFINE_SYMBOL_HANDLE(symbol)                                           \
+  String* Symbols::symbol##_handle_ = NULL;
+PREDEFINED_SYMBOL_HANDLES_LIST(DEFINE_SYMBOL_HANDLE)
+#undef DEFINE_SYMBOL_HANDLE
+
 static const char* names[] = {
   NULL,
 
@@ -25,6 +34,11 @@
 #undef DEFINE_SYMBOL_LITERAL
 };
 
+intptr_t Symbols::num_of_grows_;
+intptr_t Symbols::collision_count_[kMaxCollisionBuckets];
+
+DEFINE_FLAG(bool, dump_symbol_stats, false, "Dump symbol table statistics");
+
 
 const char* Symbols::Name(SymbolId symbol) {
   ASSERT((symbol > kIllegal) && (symbol < kMaxPredefinedId));
@@ -36,6 +50,13 @@
   // Should only be run by the vm isolate.
   ASSERT(isolate == Dart::vm_isolate());
 
+  if (FLAG_dump_symbol_stats) {
+    num_of_grows_ = 0;
+    for (intptr_t i = 0; i < kMaxCollisionBuckets; i++) {
+      collision_count_[i] = 0;
+    }
+  }
+
   // Create and setup a symbol table in the vm isolate.
   SetupSymbolTable(isolate);
 
@@ -59,6 +80,14 @@
     ASSERT(kMaxPredefinedId + c < kMaxId);
     predefined_[kMaxPredefinedId + c] = FromUTF32(&c, 1);
   }
+
+  predefined_handles_ = new ReadOnlyHandles();
+#define INITIALIZE_SYMBOL_HANDLE(symbol)                                       \
+  symbol##_handle_ = reinterpret_cast<String*>(                                \
+      predefined_handles_->AllocateHandle());                                  \
+  *symbol##_handle_ = symbol();
+PREDEFINED_SYMBOL_HANDLES_LIST(INITIALIZE_SYMBOL_HANDLE)
+#undef INITIALIZE_SYMBOL_HANDLE
 }
 
 
@@ -248,8 +277,46 @@
 }
 
 
+bool Symbols::IsPredefinedHandle(uword address) {
+  return predefined_handles_->IsValidHandle(address);
+}
+
+
+void Symbols::DumpStats() {
+  if (FLAG_dump_symbol_stats) {
+    intptr_t table_size = 0;
+    dart::Smi& used = Smi::Handle();
+    Array& symbol_table = Array::Handle(Array::null());
+
+    // First dump VM symbol table stats.
+    symbol_table = Dart::vm_isolate()->object_store()->symbol_table();
+    table_size = symbol_table.Length() - 1;
+    used ^= symbol_table.At(table_size);
+    OS::Print("VM Isolate: Number of symbols : %"Pd"\n", used.Value());
+    OS::Print("VM Isolate: Symbol table capacity : %"Pd"\n", table_size);
+
+    // Now dump regular isolate symbol table stats.
+    symbol_table = Isolate::Current()->object_store()->symbol_table();
+    table_size = symbol_table.Length() - 1;
+    used ^= symbol_table.At(table_size);
+    OS::Print("Isolate: Number of symbols : %"Pd"\n", used.Value());
+    OS::Print("Isolate: Symbol table capacity : %"Pd"\n", table_size);
+
+    // Dump overall collision and growth counts.
+    OS::Print("Number of symbol table grows = %"Pd"\n", num_of_grows_);
+    OS::Print("Collision counts on add and lookup :\n");
+    intptr_t i = 0;
+    for (i = 0; i < (kMaxCollisionBuckets - 1); i++) {
+      OS::Print("  %"Pd" collisions => %"Pd"\n", i, collision_count_[i]);
+    }
+    OS::Print("  > %"Pd" collisions => %"Pd"\n", i, collision_count_[i]);
+  }
+}
+
+
 void Symbols::GrowSymbolTable(const Array& symbol_table) {
   // TODO(iposva): Avoid exponential growth.
+  num_of_grows_ += 1;
   intptr_t table_size = symbol_table.Length() - 1;
   intptr_t new_table_size = table_size * 2;
   Array& new_symbol_table = Array::Handle(Array::New(new_table_size + 1));
@@ -263,9 +330,17 @@
       intptr_t hash = element.Hash();
       intptr_t index = hash % new_table_size;
       new_element = new_symbol_table.At(index);
+      intptr_t num_collisions = 0;
       while (!new_element.IsNull()) {
         index = (index + 1) % new_table_size;  // Move to next element.
         new_element = new_symbol_table.At(index);
+        num_collisions += 1;
+      }
+      if (FLAG_dump_symbol_stats) {
+        if (num_collisions >= kMaxCollisionBuckets) {
+          num_collisions = (kMaxCollisionBuckets - 1);
+        }
+        collision_count_[num_collisions] += 1;
       }
       new_symbol_table.SetAt(index, element);
     }
@@ -305,12 +380,20 @@
   // Last element of the array is the number of used elements.
   intptr_t table_size = symbol_table.Length() - 1;
   intptr_t index = hash % table_size;
+  intptr_t num_collisions = 0;
 
   String& symbol = String::Handle();
   symbol ^= symbol_table.At(index);
   while (!symbol.IsNull() && !symbol.Equals(characters, len)) {
     index = (index + 1) % table_size;  // Move to next element.
     symbol ^= symbol_table.At(index);
+    num_collisions += 1;
+  }
+  if (FLAG_dump_symbol_stats) {
+    if (num_collisions >= kMaxCollisionBuckets) {
+      num_collisions = (kMaxCollisionBuckets - 1);
+    }
+    collision_count_[num_collisions] += 1;
   }
   return index;  // Index of symbol if found or slot into which to add symbol.
 }
@@ -338,12 +421,20 @@
   // Last element of the array is the number of used elements.
   intptr_t table_size = symbol_table.Length() - 1;
   intptr_t index = hash % table_size;
+  intptr_t num_collisions = 0;
 
   String& symbol = String::Handle();
   symbol ^= symbol_table.At(index);
   while (!symbol.IsNull() && !symbol.Equals(str, begin_index, len)) {
     index = (index + 1) % table_size;  // Move to next element.
     symbol ^= symbol_table.At(index);
+    num_collisions += 1;
+  }
+  if (FLAG_dump_symbol_stats) {
+    if (num_collisions >= kMaxCollisionBuckets) {
+      num_collisions = (kMaxCollisionBuckets - 1);
+    }
+    collision_count_[num_collisions] += 1;
   }
   return index;  // Index of symbol if found or slot into which to add symbol.
 }
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 9900389..17d03fe 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -96,6 +96,7 @@
   V(Context, "Context")                                                        \
   V(ContextScope, "ContextScope")                                              \
   V(ICData, "ICData")                                                          \
+  V(MegamorphicCache, "MegamorphicCache")                                      \
   V(SubtypeTestCache, "SubtypeTestCache")                                      \
   V(ApiError, "ApiError")                                                      \
   V(LanguageError, "LanguageError")                                            \
@@ -144,6 +145,13 @@
   V(InvocationMirror, "_InvocationMirror")                                     \
   V(AllocateInvocationMirror, "_allocateInvocationMirror")                     \
 
+#define PREDEFINED_SYMBOL_HANDLES_LIST(V)                                      \
+  V(Dot)                                                                       \
+  V(EqualOperator)                                                             \
+  V(IndexToken)                                                                \
+  V(AssignIndexToken)                                                          \
+  V(This)                                                                      \
+
 // Contains a list of frequently used strings in a canonicalized form. This
 // list is kept in the vm_isolate in order to share the copy across isolates
 // without having to maintain copies in each isolate.
@@ -170,6 +178,12 @@
 PREDEFINED_SYMBOLS_LIST(DEFINE_SYMBOL_ACCESSOR)
 #undef DEFINE_SYMBOL_ACCESSOR
 
+  // Access methods for symbol handles stored in the vm isolate.
+#define DEFINE_SYMBOL_HANDLE_ACCESSOR(symbol)                                  \
+  static const String& symbol##Handle() { return *symbol##_handle_; }
+PREDEFINED_SYMBOL_HANDLES_LIST(DEFINE_SYMBOL_HANDLE_ACCESSOR)
+#undef DEFINE_SYMBOL_HANDLE_ACCESSOR
+
   // Initialize frequently used symbols in the vm isolate.
   static void InitOnce(Isolate* isolate);
 
@@ -210,10 +224,14 @@
     return reinterpret_cast<RawString**>(&predefined_);
   }
 
+  static bool IsPredefinedHandle(uword address);
+
+  static void DumpStats();
+
  private:
   enum {
-    kInitialVMIsolateSymtabSize = ((kMaxId + 15) & -16),
-    kInitialSymtabSize = 256
+    kInitialVMIsolateSymtabSize = 512,
+    kInitialSymtabSize = 2048
   };
 
   // Helper functions to create a symbol given a string or set of characters.
@@ -255,6 +273,37 @@
   // List of symbols that are stored in the vm isolate for easy access.
   static RawString* predefined_[kMaxId];
 
+  // Statistics used to measure the efficiency of the symbol table.
+  static const intptr_t kMaxCollisionBuckets = 10;
+  static intptr_t num_of_grows_;
+  static intptr_t collision_count_[kMaxCollisionBuckets];
+
+  // Structure for managing handles allocation for symbols that are
+  // stored in the vm isolate. We don't want these handles to be
+  // destroyed as part of the C++ static destructors and hence this
+  // object is dynamically allocated.
+  class ReadOnlyHandles {
+    public:
+      ReadOnlyHandles() { }
+      uword AllocateHandle() {
+        return handles_.AllocateScopedHandle();
+      }
+      bool IsValidHandle(uword address) {
+        return handles_.IsValidScopedHandle(address);
+      }
+
+    private:
+      VMHandles handles_;
+
+      DISALLOW_COPY_AND_ASSIGN(ReadOnlyHandles);
+  };
+  static ReadOnlyHandles* predefined_handles_;
+
+#define DECLARE_SYMBOL_HANDLE(symbol)                                          \
+  static String* symbol##_handle_;
+PREDEFINED_SYMBOL_HANDLES_LIST(DECLARE_SYMBOL_HANDLE)
+#undef DECLARE_SYMBOL_HANDLE
+
   friend class String;
   friend class SnapshotReader;
   friend class SnapshotWriter;
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 0b18707..8cc57c1 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -197,6 +197,8 @@
     'longjump.cc',
     'longjump.h',
     'longjump_test.cc',
+    'megamorphic_cache_table.cc',
+    'megamorphic_cache_table.h',
     'memory_region.cc',
     'memory_region.h',
     'memory_region_test.cc',
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 3d5feef..7f981dc 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -9,9 +9,15 @@
 import "tree/tree.dart";
 import "util/util.dart";
 
+abstract class ClosureNamer {
+  SourceString getClosureVariableName(SourceString name, int id);
+}
+
+
 class ClosureTask extends CompilerTask {
   Map<Node, ClosureClassMap> closureMappingCache;
-  ClosureTask(Compiler compiler)
+  ClosureNamer namer;
+  ClosureTask(Compiler compiler, this.namer)
       : closureMappingCache = new Map<Node, ClosureClassMap>(),
         super(compiler);
 
@@ -25,7 +31,7 @@
       if (cached != null) return cached;
 
       ClosureTranslator translator =
-          new ClosureTranslator(compiler, elements, closureMappingCache);
+          new ClosureTranslator(compiler, elements, closureMappingCache, namer);
 
       // The translator will store the computed closure-mappings inside the
       // cache. One for given node and one for each nested closure.
@@ -58,6 +64,10 @@
 
   bool isInstanceMember() => true;
   bool isAssignable() => false;
+  // The names of closure variables don't need renaming, since their use is very
+  // simple and they have 1-character names in the minified mode.
+  bool hasFixedBackendName() => true;
+  String fixedBackendName() => name.slowToString();
 
   String toString() => "ClosureFieldElement($name)";
 }
@@ -151,9 +161,9 @@
   final Map<Element, Element> parametersWithSentinel;
 
   ClosureClassMap(this.closureElement,
-              this.closureClassElement,
-              this.callElement,
-              this.thisElement)
+                  this.closureClassElement,
+                  this.callElement,
+                  this.thisElement)
       : this.freeVariableMapping = new Map<Element, Element>(),
         this.capturedFieldMapping = new Map<Element, Element>(),
         this.capturingScopes = new Map<Node, ClosureScope>(),
@@ -167,6 +177,7 @@
   final Compiler compiler;
   final TreeElements elements;
   int closureFieldCounter = 0;
+  int boxedFieldCounter = 0;
   bool inTryStatement = false;
   final Map<Node, ClosureClassMap> closureMappingCache;
 
@@ -190,9 +201,12 @@
   // The closureData of the currentFunctionElement.
   ClosureClassMap closureData;
 
+  ClosureNamer namer;
+
   bool insideClosure = false;
 
-  ClosureTranslator(this.compiler, this.elements, this.closureMappingCache)
+  ClosureTranslator(this.compiler, this.elements, this.closureMappingCache,
+                    this.namer)
       : capturedVariableMapping = new Map<Element, Element>(),
         closures = <Expression>[],
         mutatedVariables = new Set<Element>();
@@ -225,6 +239,7 @@
       // The captured variables that need to be stored in a field of the closure
       // class.
       Set<Element> fieldCaptures = new Set<Element>();
+      Set<Element> boxes = new Set<Element>();
       ClosureClassMap data = closureMappingCache[closure];
       Map<Element, Element> freeVariableMapping = data.freeVariableMapping;
       // We get a copy of the keys and iterate over it, to avoid modifications
@@ -244,26 +259,30 @@
           freeVariableMapping[fromElement] = updatedElement;
           Element boxElement = updatedElement.enclosingElement;
           assert(boxElement.kind == ElementKind.VARIABLE);
-          fieldCaptures.add(boxElement);
+          boxes.add(boxElement);
         }
       });
       ClassElement closureElement = data.closureClassElement;
-      assert(closureElement != null || fieldCaptures.isEmpty);
-      for (Element capturedElement in fieldCaptures) {
-        SourceString name;
-        if (capturedElement is BoxElement) {
-          // The name is already mangled.
-          name = capturedElement.name;
-        } else {
-          int id = closureFieldCounter++;
-          name = new SourceString("${capturedElement.name.slowToString()}_$id");
-        }
+      assert(closureElement != null ||
+             (fieldCaptures.isEmpty && boxes.isEmpty));
+      void addElement(Element element, SourceString name) {
         Element fieldElement = new ClosureFieldElement(name, closureElement);
         closureElement.backendMembers =
             closureElement.backendMembers.prepend(fieldElement);
-        data.capturedFieldMapping[fieldElement] = capturedElement;
-        freeVariableMapping[capturedElement] = fieldElement;
+        data.capturedFieldMapping[fieldElement] = element;
+        freeVariableMapping[element] = fieldElement;
       }
+      // Add the box elements first so we get the same ordering.
+      for (Element capturedElement in boxes) {
+        addElement(capturedElement, capturedElement.name);
+      }
+      for (Element capturedElement in fieldCaptures) {
+        int id = closureFieldCounter++;
+        SourceString name =
+            namer.getClosureVariableName(capturedElement.name, id);
+        addElement(capturedElement, name);
+      }
+      closureElement.backendMembers = closureElement.backendMembers.reverse();
     }
   }
 
@@ -418,17 +437,18 @@
         if (box == null) {
           // TODO(floitsch): construct better box names.
           SourceString boxName =
-              new SourceString("box_${closureFieldCounter++}");
+              namer.getClosureVariableName(const SourceString('box'),
+                                           closureFieldCounter++);
           box = new BoxElement(boxName, currentElement);
         }
-        // TODO(floitsch): construct better boxed names.
         String elementName = element.name.slowToString();
-        // We are currently using the name in an HForeign which could replace
-        // "$X" with something else.
-        String escaped = elementName.replaceAll("\$", "_");
         SourceString boxedName =
-            new SourceString("${escaped}_${closureFieldCounter++}");
+            namer.getClosureVariableName(new SourceString(elementName),
+                                         boxedFieldCounter++);
         Element boxed = new Element(boxedName, ElementKind.FIELD, box);
+        // No need to rename the fields of a box, so we give them a native name
+        // right now.
+        boxed.setFixedBackendName(boxedName.slowToString());
         scopeMapping[element] = boxed;
         capturedVariableMapping[element] = boxed;
       }
@@ -478,7 +498,7 @@
   }
 
   /** Returns a non-unique name for the given closure element. */
-  String closureName(Element element) {
+  String computeClosureName(Element element) {
     Link<String> parts = const Link<String>();
     SourceString ownName = element.name;
     if (ownName == null || ownName.stringValue == "") {
@@ -505,7 +525,7 @@
   }
 
   ClosureClassMap globalizeClosure(FunctionExpression node, Element element) {
-    SourceString closureName = new SourceString(closureName(element));
+    SourceString closureName = new SourceString(computeClosureName(element));
     ClassElement globalizedElement = new ClosureClassElement(
         closureName, compiler, element, element.getCompilationUnit());
     FunctionElement callElement =
@@ -513,7 +533,7 @@
                                  element,
                                  globalizedElement);
     globalizedElement.backendMembers =
-        const Link<Element>().prepend(callElement);
+        globalizedElement.backendMembers.prepend(callElement);
     // The nested function's 'this' is the same as the one for the outer
     // function. It could be [null] if we are inside a static method.
     Element thisElement = closureData.thisElement;
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 7eb4167..cb1439a 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -75,11 +75,6 @@
     SourceString helperName = const SourceString('createRuntimeType');
     createRuntimeTypeFunction = compiler.findHelper(helperName);
     registerStaticUse(createRuntimeTypeFunction);
-    // TODO(kasperl): It looks a bit fishy that we have to register
-    // this in the resolution queue too. Can we do this in the
-    // resolver instead? That would be more consistent with how we
-    // register all the other resolution work items.
-    compiler.enqueuer.resolution.registerStaticUse(createRuntimeTypeFunction);
   }
 
   /**
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 1aa0452..1de80f0 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -128,6 +128,7 @@
   Element _currentElement;
   LibraryElement coreLibrary;
   LibraryElement isolateLibrary;
+  LibraryElement isolateHelperLibrary;
   LibraryElement jsHelperLibrary;
   LibraryElement interceptorsLibrary;
   LibraryElement foreignLibrary;
@@ -151,6 +152,7 @@
   Element identicalFunction;
   Element functionApplyMethod;
   Element invokeOnMethod;
+  Element createInvocationMirrorElement;
 
   Element get currentElement => _currentElement;
   withCurrentElement(Element element, f()) {
@@ -162,6 +164,7 @@
       if (!hasCrashed) {
         SourceSpan span = spanFromSpannable(ex.node);
         reportDiagnostic(span, ex.message, api.Diagnostic.ERROR);
+        pleaseReportCrash();
       }
       hasCrashed = true;
       throw;
@@ -204,6 +207,8 @@
   static const SourceString CALL_OPERATOR_NAME = const SourceString('call');
   static const SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod');
   static const int NO_SUCH_METHOD_ARG_COUNT = 1;
+  static const SourceString CREATE_INVOCATION_MIRROR =
+      const SourceString('createInvocationMirror');
   static const SourceString INVOKE_ON = const SourceString('invokeOn');
   static const SourceString RUNTIME_TYPE = const SourceString('runtimeType');
   static const SourceString START_ROOT_ISOLATE =
@@ -241,11 +246,17 @@
         progress = new Stopwatch() {
     progress.start();
     world = new World(this);
-    backend = emitJavaScript ?
-        new js_backend.JavaScriptBackend(this,
-                                         generateSourceMap,
-                                         disallowUnsafeEval) :
-        new dart_backend.DartBackend(this, strips);
+
+    closureMapping.ClosureNamer closureNamer;
+    if (emitJavaScript) {
+      js_backend.JavaScriptBackend jsBackend =
+          new js_backend.JavaScriptBackend(this, generateSourceMap,
+                                           disallowUnsafeEval);
+      closureNamer = jsBackend.namer;
+      backend = jsBackend;
+    } else {
+      backend = new dart_backend.DartBackend(this, strips);
+    }
 
     // No-op in production mode.
     validator = new TreeValidatorTask(this);
@@ -258,7 +269,7 @@
       parser = new ParserTask(this),
       patchParser = new PatchParserTask(this),
       resolver = new ResolverTask(this),
-      closureToClassMapper = new closureMapping.ClosureTask(this),
+      closureToClassMapper = new closureMapping.ClosureTask(this, closureNamer),
       checker = new TypeCheckerTask(this),
       typesTask = new ti.TypesTask(this, enableConcreteTypeInference),
       constantHandler = new ConstantHandler(this, backend.constantSystem),
@@ -304,6 +315,10 @@
     reportDiagnostic(spanFromElement(element),
                      MessageKind.COMPILER_CRASHED.error().toString(),
                      api.Diagnostic.CRASH);
+    pleaseReportCrash();
+  }
+
+  void pleaseReportCrash() {
     print(MessageKind.PLEASE_REPORT_THE_CRASH.message([BUILD_ID]));
   }
 
@@ -379,8 +394,8 @@
     enqueuer.resolution.registerInvocation(NO_SUCH_METHOD, selector);
     enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, selector);
 
-    Element createInvocationMirrorElement =
-        findHelper(const SourceString('createInvocationMirror'));
+    createInvocationMirrorElement =
+        findHelper(CREATE_INVOCATION_MIRROR);
     enqueuer.resolution.addToWorkList(createInvocationMirrorElement);
     enqueuer.codegen.addToWorkList(createInvocationMirrorElement);
   }
@@ -388,12 +403,33 @@
   void enableIsolateSupport(LibraryElement element) {
     // TODO(ahe): Move this method to Enqueuer.
     isolateLibrary = element.patch;
-    enqueuer.resolution.addToWorkList(isolateLibrary.find(START_ROOT_ISOLATE));
+    isolateHelperLibrary = scanBuiltinLibrary('_isolate_helper');
+    importForeignLibrary(isolateHelperLibrary);
+    importHelperLibrary(isolateHelperLibrary);
+
+    libraryLoader.importLibrary(isolateLibrary, isolateHelperLibrary, null);
     enqueuer.resolution.addToWorkList(
-        isolateLibrary.find(const SourceString('_currentIsolate')));
+        isolateHelperLibrary.find(START_ROOT_ISOLATE));
     enqueuer.resolution.addToWorkList(
-        isolateLibrary.find(const SourceString('_callInIsolate')));
-    enqueuer.codegen.addToWorkList(isolateLibrary.find(START_ROOT_ISOLATE));
+        isolateHelperLibrary.find(const SourceString('_currentIsolate')));
+    enqueuer.resolution.addToWorkList(
+        isolateHelperLibrary.find(const SourceString('_callInIsolate')));
+    enqueuer.codegen.addToWorkList(
+        isolateHelperLibrary.find(START_ROOT_ISOLATE));
+
+    // The helper library does not use the native language extension,
+    // so we manually set the native classes this library defines.
+    // TODO(ngeoffray): Enable annotations on these classes.
+    ClassElement cls = isolateHelperLibrary.find(const SourceString('_Window'));
+    cls.setNative('"*DOMWindow"');
+
+    cls = isolateHelperLibrary.find(const SourceString('_WorkerStub'));
+    cls.setNative('"*Worker"');
+
+    enqueuer.resolution.nativeEnqueuer.processNativeClassesInLibrary(
+        isolateHelperLibrary);
+    enqueuer.codegen.nativeEnqueuer.processNativeClassesInLibrary(
+        isolateHelperLibrary);
   }
 
   bool hasIsolateSupport() => isolateLibrary != null;
@@ -486,7 +522,7 @@
 
   /** Define the JS helper functions in the given library. */
   void importForeignLibrary(LibraryElement library) {
-    if (jsHelperLibrary != null) {
+    if (foreignLibrary != null) {
       libraryLoader.importLibrary(library, foreignLibrary, null);
     }
   }
@@ -499,7 +535,6 @@
         'dart/tests/compiler/dart2js_native');
     if (nativeTest
         || libraryName == 'dart:mirrors'
-        || libraryName == 'dart:isolate'
         || libraryName == 'dart:math'
         || libraryName == 'dart:html'
         || libraryName == 'dart:html_common'
@@ -765,12 +800,13 @@
     reportDiagnostic(span, "$message", kind);
   }
 
-  void onDeprecatedFeature(Spannable span, String feature) {
+  /// Returns true if a diagnostic was emitted.
+  bool onDeprecatedFeature(Spannable span, String feature) {
     if (currentElement == null)
       throw new SpannableAssertionFailure(span, feature);
     if (!checkDeprecationInSdk &&
         currentElement.getLibrary().isPlatformLibrary) {
-      return;
+      return false;
     }
     var kind = rejectDeprecatedFeatures
         ? api.Diagnostic.ERROR : api.Diagnostic.WARNING;
@@ -778,6 +814,7 @@
         ? MessageKind.DEPRECATED_FEATURE_ERROR.error([feature])
         : MessageKind.DEPRECATED_FEATURE_WARNING.error([feature]);
     reportMessage(spanFromSpannable(span), message, kind);
+    return true;
   }
 
   void reportDiagnostic(SourceSpan span, String message, api.Diagnostic kind);
@@ -804,7 +841,7 @@
     if (Elements.isErroneousElement(element)) {
       element = element.enclosingElement;
     }
-    if (element.position() == null) {
+    if (element.position() == null && !element.isCompilationUnit()) {
       // Sometimes, the backend fakes up elements that have no
       // position. So we use the enclosing element instead. It is
       // not a good error location, but cancel really is "internal
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index fb1cf88..4735b7b 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -252,6 +252,9 @@
         fixedMemberNames.add(element.name.slowToString());
       });
     }
+    // The VM will automatically invoke the call method of objects
+    // that are invoked as functions. Make sure to not rename that.
+    fixedMemberNames.add('call');
     // TODO(antonm): TypeError.srcType and TypeError.dstType are defined in
     // runtime/lib/error.dart. Overall, all DartVM specific libs should be
     // accounted for.
diff --git a/sdk/lib/_internal/compiler/implementation/diagnostic_listener.dart b/sdk/lib/_internal/compiler/implementation/diagnostic_listener.dart
index 19f5501..c20e6cb 100644
--- a/sdk/lib/_internal/compiler/implementation/diagnostic_listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/diagnostic_listener.dart
@@ -20,5 +20,6 @@
 
   void reportMessage(SourceSpan span, Diagnostic message, api.Diagnostic kind);
 
-  void onDeprecatedFeature(Spannable span, String feature);
+  /// Returns true if a diagnostic was emitted.
+  bool onDeprecatedFeature(Spannable span, String feature);
 }
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index d0caf29..a67fb06 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -58,8 +58,6 @@
   static const int TYPE_VARIABLE = 128;
 
   static const int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE;
-
-  static const int IS_EXTENDABLE = CLASS | ALIAS;
 }
 
 class ElementKind {
@@ -191,7 +189,6 @@
   bool isAccessor() => isGetter() || isSetter();
   bool isLibrary() => identical(kind, ElementKind.LIBRARY);
   bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0;
-  bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0;
 
   /** See [ErroneousElement] for documentation. */
   bool isErroneous() => false;
@@ -350,11 +347,19 @@
     }
   }
 
-  String _nativeName = null;
-  bool isNative() => _nativeName != null;
-  String nativeName() => _nativeName;
-  /// Marks this element as a native element.
-  void setNative(String name) { _nativeName = name; }
+  String _fixedBackendName = null;
+  bool _isNative = false;
+  bool isNative() => _isNative;
+  bool hasFixedBackendName() => _fixedBackendName != null;
+  String fixedBackendName() => _fixedBackendName;
+  // Marks this element as a native element.
+  void setNative(String name) {
+    _isNative = true;
+    _fixedBackendName = name;
+  }
+  void setFixedBackendName(String name) {
+    _fixedBackendName = name;
+  }
 
   FunctionElement asFunctionElement() => null;
 
@@ -1756,6 +1761,9 @@
 
   bool isInterface() => false;
   bool isNative() => nativeTagInfo != null;
+  void setNative(String name) {
+    nativeTagInfo = new SourceString(name);
+  }
   int get hashCode => id;
 
   Scope buildScope() => new ClassScope(enclosingElement.buildScope(), this);
@@ -1857,6 +1865,16 @@
     return new SourceString('$r\$$s');
   }
 
+  static SourceString deconstructConstructorName(SourceString name,
+                                                 ClassElement holder) {
+    String r = '${holder.name.slowToString()}\$';
+    String s = name.slowToString();
+    if (s.startsWith(r)) {
+      return new SourceString(s.substring(r.length));
+    }
+    return null;
+  }
+
   /**
    * Map an operator-name to a valid Dart identifier.
    *
diff --git a/sdk/lib/_internal/compiler/implementation/js/nodes.dart b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
index ec1469c..f206c0e 100644
--- a/sdk/lib/_internal/compiler/implementation/js/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
@@ -149,6 +149,8 @@
 
   accept(NodeVisitor visitor);
   void visitChildren(NodeVisitor visitor);
+
+  VariableUse asVariableUse() => null;
 }
 
 class Program extends Node {
@@ -657,6 +659,8 @@
   VariableUse(String name) : super(name);
 
   accept(NodeVisitor visitor) => visitor.visitVariableUse(this);
+
+  VariableUse asVariableUse() => this;
 }
 
 class VariableDeclaration extends VariableReference {
diff --git a/sdk/lib/_internal/compiler/implementation/js/printer.dart b/sdk/lib/_internal/compiler/implementation/js/printer.dart
index ce2e056..048dc71 100644
--- a/sdk/lib/_internal/compiler/implementation/js/printer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/printer.dart
@@ -12,7 +12,7 @@
   bool inForInit = false;
   bool atStatementBegin = false;
   final DanglingElseVisitor danglingElseVisitor;
-  final Namer namer;
+  final LocalNamer localNamer;
   bool pendingSemicolon = false;
   bool pendingSpace = false;
   static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]');
@@ -22,11 +22,11 @@
         this.compiler = compiler,
         outBuffer = new leg.CodeBuffer(),
         danglingElseVisitor = new DanglingElseVisitor(compiler),
-        namer = determineRenamer(compiler.enableMinification,
-                                 allowVariableMinification);
+        localNamer = determineRenamer(compiler.enableMinification,
+                                      allowVariableMinification);
 
-  static Namer determineRenamer(bool shouldCompressOutput,
-                                bool allowVariableMinification) {
+  static LocalNamer determineRenamer(bool shouldCompressOutput,
+                                     bool allowVariableMinification) {
     return (shouldCompressOutput && allowVariableMinification)
         ? new MinifyRenamer() : new IdentityNamer();
   }
@@ -391,7 +391,7 @@
       visitNestedExpression(name, PRIMARY,
                             newInForInit: false, newAtStatementBegin: false);
     }
-    namer.enterScope(vars);
+    localNamer.enterScope(vars);
     out("(");
     if (fun.params != null) {
       visitCommaSeparated(fun.params, PRIMARY,
@@ -399,7 +399,7 @@
     }
     out(")");
     blockBody(fun.body, needsSeparation: false, needsNewline: false);
-    namer.leaveScope();
+    localNamer.leaveScope();
   }
 
   visitFunctionDeclaration(FunctionDeclaration declaration) {
@@ -639,7 +639,7 @@
   }
 
   visitVariableUse(VariableUse ref) {
-    out(namer.getName(ref.name));
+    out(localNamer.getName(ref.name));
   }
 
   visitThis(This node) {
@@ -647,11 +647,11 @@
   }
 
   visitVariableDeclaration(VariableDeclaration decl) {
-    out(namer.getName(decl.name));
+    out(localNamer.getName(decl.name));
   }
 
   visitParameter(Parameter param) {
-    out(namer.getName(param.name));
+    out(localNamer.getName(param.name));
   }
 
   bool isDigit(int charCode) {
@@ -944,7 +944,7 @@
 }
 
 
-abstract class Namer {
+abstract class LocalNamer {
   String getName(String oldName);
   String declareVariable(String oldName);
   String declareParameter(String oldName);
@@ -953,7 +953,7 @@
 }
 
 
-class IdentityNamer implements Namer {
+class IdentityNamer implements LocalNamer {
   String getName(String oldName) => oldName;
   String declareVariable(String oldName) => oldName;
   String declareParameter(String oldName) => oldName;
@@ -962,7 +962,7 @@
 }
 
 
-class MinifyRenamer implements Namer {
+class MinifyRenamer implements LocalNamer {
   final List<Map<String, String>> maps = [];
   final List<int> parameterNumberStack = [];
   final List<int> variableNumberStack = [];
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index a566b0f..902414d 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -700,10 +700,8 @@
 
   final RuntimeTypeInformation rti;
 
-  JavaScriptBackend(Compiler compiler,
-                    bool generateSourceMap,
-                    bool disableEval)
-      : namer = new Namer(compiler),
+  JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval)
+      : namer = determineNamer(compiler),
         returnInfo = new Map<Element, ReturnInfo>(),
         invalidateAfterCodegen = new List<Element>(),
         interceptors = new Interceptors(compiler),
@@ -724,6 +722,12 @@
     fieldTypes = new FieldTypesRegistry(this);
   }
 
+  static Namer determineNamer(Compiler compiler) {
+    return compiler.enableMinification ?
+        new MinifyNamer(compiler) :
+        new Namer(compiler);
+  }
+
   bool isInterceptorClass(Element element) {
     if (element == null) return false;
     return interceptedClasses.containsKey(element);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index c5a85ca..86717ae 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -131,11 +131,11 @@
   js.Expression emitCanonicalVersion(Constant constant) {
     String name = namer.constantName(constant);
     if (inIsolateInitializationContext) {
-      //  $ISOLATE.$ISOLATE_PROPERTIES.$name
+      //  $isolateName.$isolatePropertiesName.$name
       return new js.PropertyAccess.field(
           new js.PropertyAccess.field(
-              new js.VariableUse(namer.ISOLATE),
-              namer.ISOLATE_PROPERTIES),
+              new js.VariableUse(namer.isolateName),
+              namer.isolatePropertiesName),
           name);
     } else {
       return new js.PropertyAccess.field(
@@ -222,7 +222,7 @@
   js.Expression visitList(ListConstant constant) {
     return new js.Call(
         new js.PropertyAccess.field(
-            new js.VariableUse(namer.ISOLATE),
+            new js.VariableUse(namer.isolateName),
             'makeConstantList'),
         [new js.ArrayInitializer.from(_array(constant.entries))]);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 4d25e3a..8b808f0 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -45,6 +45,10 @@
   String isolateProperties;
   String classesCollector;
 
+  String get _ => compiler.enableMinification ? "" : " ";
+  String get n => compiler.enableMinification ? "" : "\n";
+  String get N => compiler.enableMinification ? "\n" : ";\n";
+
   /**
    * A cache of closures that are used to closurize instance methods.
    * A closure is dynamically bound to the instance used when
@@ -59,6 +63,7 @@
    */
   final Map<int, String> interceptorClosureCache;
   Set<ClassElement> checkedClasses;
+  Set<TypedefElement> checkedTypedefs;
 
   final bool generateSourceMap;
 
@@ -76,8 +81,13 @@
   void computeRequiredTypeChecks() {
     assert(checkedClasses == null);
     checkedClasses = new Set<ClassElement>();
+    checkedTypedefs = new Set<TypedefElement>();
     compiler.codegenWorld.isChecks.forEach((DartType t) {
-      if (t is InterfaceType) checkedClasses.add(t.element);
+      if (t is InterfaceType) {
+        checkedClasses.add(t.element);
+      } else if (t is TypedefType) {
+        checkedTypedefs.add(t.element);
+      }
     });
   }
 
@@ -92,50 +102,72 @@
   String get name => 'CodeEmitter';
 
   String get defineClassName
-      => '${namer.ISOLATE}.\$defineClass';
+      => '${namer.isolateName}.\$defineClass';
   String get currentGenerateAccessorName
       => '${namer.CURRENT_ISOLATE}.\$generateAccessor';
   String get generateAccessorHolder
       => '$isolatePropertiesName.\$generateAccessor';
   String get finishClassesName
-      => '${namer.ISOLATE}.\$finishClasses';
+      => '${namer.isolateName}.\$finishClasses';
   String get finishIsolateConstructorName
-      => '${namer.ISOLATE}.\$finishIsolateConstructor';
+      => '${namer.isolateName}.\$finishIsolateConstructor';
   String get pendingClassesName
-      => '${namer.ISOLATE}.\$pendingClasses';
+      => '${namer.isolateName}.\$pendingClasses';
   String get isolatePropertiesName
-      => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}';
+      => '${namer.isolateName}.${namer.isolatePropertiesName}';
   String get supportsProtoName
       => 'supportsProto';
   String get lazyInitializerName
-      => '${namer.ISOLATE}.\$lazy';
+      => '${namer.isolateName}.\$lazy';
 
-  final String GETTER_SUFFIX = "?";
-  final String SETTER_SUFFIX = "!";
-  final String GETTER_SETTER_SUFFIX = "=";
+  // Property name suffixes.  If the accessors are renaming then the format
+  // is <accessorName>:<fieldName><suffix>.  We use the suffix to know whether
+  // to look for the ':' separator in order to avoid doing the indexOf operation
+  // on every single property (they are quite rare).  None of these characters
+  // are legal in an identifier and they are related by bit patterns.
+  // setter          <          0x3c
+  // both            =          0x3d
+  // getter          >          0x3e
+  // renaming setter |          0x7c
+  // renaming both   }          0x7d
+  // renaming getter ~          0x7e
+  const SUFFIX_MASK = 0x3f;
+  const FIRST_SUFFIX_CODE = 0x3c;
+  const SETTER_CODE = 0x3c;
+  const GETTER_SETTER_CODE = 0x3d;
+  const GETTER_CODE = 0x3e;
+  const RENAMING_FLAG = 0x40;
+  String needsGetterCode(String variable) => '($variable & 3) > 0';
+  String needsSetterCode(String variable) => '($variable & 2) == 0';
+  String isRenaming(String variable) => '($variable & $RENAMING_FLAG) != 0';
 
   String get generateAccessorFunction {
     return """
 function generateAccessor(field, prototype) {
   var len = field.length;
-  var lastChar = field[len - 1];
-  var needsGetter = lastChar == '$GETTER_SUFFIX' || lastChar == '$GETTER_SETTER_SUFFIX';
-  var needsSetter = lastChar == '$SETTER_SUFFIX' || lastChar == '$GETTER_SETTER_SUFFIX';
-  if (needsGetter || needsSetter) field = field.substring(0, len - 1);
-  if (needsGetter) {
-    var getterString = "return this." + field + ";";
-"""
-  /* The supportsProtoCheck below depends on the getter/setter convention.
-         When changing here, update the protoCheck too. */
-  """
-      prototype["get\$" + field] = new Function(getterString);
+  var lastCharCode = field.charCodeAt(len - 1);
+  var needsAccessor = (lastCharCode & $SUFFIX_MASK) >= $FIRST_SUFFIX_CODE;
+  if (needsAccessor) {
+    var needsGetter = ${needsGetterCode('lastCharCode')};
+    var needsSetter = ${needsSetterCode('lastCharCode')};
+    var renaming = ${isRenaming('lastCharCode')};
+    var accessorName = field = field.substring(0, len - 1);
+    if (renaming) {
+      var divider = field.indexOf(":");
+      accessorName = field.substring(0, divider);
+      field = field.substring(divider + 1);
+    }
+    if (needsGetter) {
+      var getterString = "return this." + field + ";";
+      prototype["get\$" + accessorName] = new Function(getterString);
     }
     if (needsSetter) {
       var setterString = "this." + field + " = v;";
-      prototype["set\$" + field] = new Function("v", setterString);
+      prototype["set\$" + accessorName] = new Function("v", setterString);
     }
-    return field;
-  }""";
+  }
+  return field;
+}""";
   }
 
   String get defineClassFunction {
@@ -193,7 +225,7 @@
 var tmp = $defineClassName('c', ['f?'], {}).prototype;
 if (tmp.__proto__) {
   tmp.__proto__ = {};
-  if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true;
+  if (typeof tmp.get\$f !== 'undefined') $supportsProtoName = true;
 }
 ''';
   }
@@ -217,10 +249,17 @@
   for (var cls in collectedClasses) {
     if (hasOwnProperty.call(collectedClasses, cls)) {
       var desc = collectedClasses[cls];
-'''/* Get the superclass and the fields in the format Super;field1,field2 from
-      the null-string property on the descriptor. */'''
-      var s = desc[''].split(';'), supr = s[0];
-      var fields = s[1] == '' ? [] : s[1].split(',');
+'''/* The 'fields' are either a constructor function or a string encoding
+      fields, constructor and superclass.  Get the superclass and the fields
+      in the format Super;field1,field2 from the null-string property on the
+      descriptor. */'''
+      var fields = desc[''], supr;
+      if (typeof fields == 'string') {
+        var s = fields.split(';'); supr = s[0];
+        fields = s[1] == '' ? [] : s[1].split(',');
+      } else {
+        supr = desc['super'];
+      }
       $isolatePropertiesName[cls] = $defineClassName(cls, fields, desc);
       if (supr) $pendingClassesName[cls] = supr;
     }
@@ -265,7 +304,7 @@
   }
 
   String get finishIsolateConstructorFunction {
-    String isolate = namer.ISOLATE;
+    String isolate = namer.isolateName;
     // We replace the old Isolate function with a new one that initializes
     // all its field with the initial (and often final) value of all globals.
     // This has two advantages:
@@ -287,10 +326,10 @@
     // We also copy over old values like the prototype, and the
     // isolateProperties themselves.
     return """function(oldIsolate) {
-  var isolateProperties = oldIsolate.${namer.ISOLATE_PROPERTIES};
+  var isolateProperties = oldIsolate.${namer.isolatePropertiesName};
   var isolatePrototype = oldIsolate.prototype;
   var str = "{\\n";
-  str += "var properties = $isolate.${namer.ISOLATE_PROPERTIES};\\n";
+  str += "var properties = $isolate.${namer.isolatePropertiesName};\\n";
   for (var staticName in isolateProperties) {
     if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) {
       str += "this." + staticName + "= properties." + staticName + ";\\n";
@@ -300,7 +339,7 @@
   var newIsolate = new Function(str);
   newIsolate.prototype = isolatePrototype;
   isolatePrototype.constructor = newIsolate;
-  newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties;
+  newIsolate.${namer.isolatePropertiesName} = isolateProperties;
   return newIsolate;
 }""";
   }
@@ -349,30 +388,30 @@
     if (needsDefineClass) {
       // Declare function called generateAccessor.  This is used in
       // defineClassFunction (it's a local declaration in init()).
-      buffer.add("$generateAccessorFunction;\n");
-      buffer.add("$generateAccessorHolder = generateAccessor\n");
-      buffer.add("$defineClassName = $defineClassFunction;\n");
+      buffer.add("$generateAccessorFunction$N");
+      buffer.add("$generateAccessorHolder = generateAccessor$N");
+      buffer.add("$defineClassName = $defineClassFunction$N");
       buffer.add(protoSupportCheck);
-      buffer.add("$pendingClassesName = {};\n");
-      buffer.add("$finishClassesName = $finishClassesFunction;\n");
+      buffer.add("$pendingClassesName = {}$N");
+      buffer.add("$finishClassesName = $finishClassesFunction$N");
     }
   }
 
   void addLazyInitializerFunctionIfNecessary(CodeBuffer buffer) {
     if (needsLazyInitializer) {
-      buffer.add("$lazyInitializerName = $lazyInitializerFunction;\n");
+      buffer.add("$lazyInitializerName = $lazyInitializerFunction$N");
     }
   }
 
   void emitFinishIsolateConstructor(CodeBuffer buffer) {
     String name = finishIsolateConstructorName;
     String value = finishIsolateConstructorFunction;
-    buffer.add("$name = $value;\n");
+    buffer.add("$name = $value$N");
   }
 
   void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) {
-    String isolate = namer.ISOLATE;
-    buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n");
+    String isolate = namer.isolateName;
+    buffer.add("$isolate = $finishIsolateConstructorName($isolate)$N");
   }
 
   /**
@@ -475,7 +514,7 @@
     });
 
     List<js.Statement> body;
-    if (member.isNative()) {
+    if (member.hasFixedBackendName()) {
       body = nativeEmitter.generateParameterStubStatements(
           member, invocationName, parametersBuffer, argumentsBuffer,
           indexOfLastOptionalArgumentInParameters);
@@ -527,7 +566,7 @@
     // on A and a typed selector on B could yield the same stub.
     Set<String> generatedStubNames = new Set<String>();
     if (compiler.enabledFunctionApply
-        && member.name == Namer.CLOSURE_INVOCATION_NAME) {
+        && member.name == namer.closureInvocationSelectorName) {
       // If [Function.apply] is called, we pessimistically compile all
       // possible stubs for this closure.
       FunctionSignature signature = member.computeSignature(compiler);
@@ -621,8 +660,8 @@
 
   String compiledFieldName(Element member) {
     assert(member.isField());
-    return member.isNative()
-        ? member.name.slowToString()
+    return member.hasFixedBackendName()
+        ? member.fixedBackendName()
         : namer.getName(member);
   }
 
@@ -673,7 +712,7 @@
       if (emitLeadingComma) buffer.add(',');
       emitLeadingComma = true;
       buffer.add('\n');
-      buffer.add(' $name: ');
+      buffer.add('$_$name:$_');
       buffer.add(memberBuffer);
     }
 
@@ -693,11 +732,11 @@
         },
         includeBackendMembers: true);
 
-    generateIsTestsOn(classElement, (ClassElement other) {
+    generateIsTestsOn(classElement, (Element other) {
       String code;
-      if (other.isObject(compiler)) return;
+      if (compiler.objectClass == other) return;
       if (nativeEmitter.requiresNativeIsCheck(other)) {
-        code = 'function() { return true; }';
+        code = 'function()$_{${_}return true;$_}';
       } else {
         code = 'true';
       }
@@ -726,6 +765,7 @@
   void visitClassFields(ClassElement classElement,
                         void addField(Element member,
                                       String name,
+                                      String accessorName,
                                       bool needsGetter,
                                       bool needsSetter,
                                       bool needsCheckedSetter)) {
@@ -763,8 +803,8 @@
         String accessorName = isShadowed
             ? namer.shadowedFieldName(member)
             : namer.getName(member);
-        String fieldName = member.isNative()
-            ? member.nativeName()
+        String fieldName = member.hasFixedBackendName()
+            ? member.fixedBackendName()
             : accessorName;
         bool needsCheckedSetter = false;
         if (needsSetter && compiler.enableTypeAssertions
@@ -775,6 +815,7 @@
         // Getters and setters with suffixes will be generated dynamically.
         addField(member,
                  fieldName,
+                 accessorName,
                  needsGetter,
                  needsSetter,
                  needsCheckedSetter);
@@ -791,16 +832,18 @@
         includeSuperMembers: isInstantiated && !classElement.isNative());
   }
 
-  void generateGetter(Element member, String fieldName, CodeBuffer buffer) {
-    String getterName = namer.getterName(member.getLibrary(), member.name);
-    buffer.add("$getterName: function() { return this.$fieldName; }");
-  }
-
-  void generateSetter(Element member, String fieldName, CodeBuffer buffer) {
-    String setterName = namer.setterName(member.getLibrary(), member.name);
-    buffer.add("$setterName: function(v) { this.$fieldName = v; }");
-  }
-
+  void generateGetter(Element member, String fieldName, String accessorName,
+                      CodeBuffer buffer) {      
+    String getterName = namer.getterNameFromAccessorName(accessorName);
+    buffer.add("$getterName: function() { return this.$fieldName; }");    
+  }       
+  
+  void generateSetter(Element member, String fieldName, String accessorName,
+                      CodeBuffer buffer) {      
+    String setterName = namer.setterNameFromAccessorName(accessorName);
+    buffer.add("$setterName: function(v) { this.$fieldName = v; }");      
+  }       
+  
   bool canGenerateCheckedSetter(Element member) {
     DartType type = member.computeType(compiler);
     if (type.element.isTypeVariable()
@@ -814,6 +857,7 @@
 
   void generateCheckedSetter(Element member,
                              String fieldName,
+                             String accessorName,
                              CodeBuffer buffer) {
     assert(canGenerateCheckedSetter(member));
     DartType type = member.computeType(compiler);
@@ -822,38 +866,46 @@
     String helperName = namer.isolateAccess(helperElement);
     String additionalArgument = '';
     if (helperElement.computeSignature(compiler).parameterCount != 1) {
-      additionalArgument = ", '${namer.operatorIs(type.element)}'";
+      additionalArgument = ",$_'${namer.operatorIs(type.element)}'";
     }
-    String setterName = namer.setterName(member.getLibrary(), member.name);
-    buffer.add("$setterName: function(v) { "
-        "this.$fieldName = $helperName(v$additionalArgument); }");
+    String setterName = namer.setterNameFromAccessorName(accessorName);
+    buffer.add("$setterName:${_}function(v)$_{$_"
+        "this.$fieldName$_=$_$helperName(v$additionalArgument);}");
   }
 
   void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) {
     /* Do nothing. */
   }
 
+  void emitSuper(String superName, CodeBuffer buffer) {
+    /* Do nothing. */
+  }
+
   void emitClassFields(ClassElement classElement,
                        CodeBuffer buffer,
                        bool emitEndingComma,
                        { String superClass: "",
-                         bool isNative: false}) {
+                         bool classIsNative: false}) {
     bool isFirstField = true;
     bool isAnythingOutput = false;
-    if (!isNative) {
+    if (!classIsNative) {
       buffer.add('"":"$superClass;');
       isAnythingOutput = true;
     }
     visitClassFields(classElement, (Element member,
                                     String name,
+                                    String accessorName,
                                     bool needsGetter,
                                     bool needsSetter,
                                     bool needsCheckedSetter) {
-      if (!getterAndSetterCanBeImplementedByFieldSpec(
-          member, name, needsGetter, needsSetter)) {
-        return;
-      }
-      if (!isNative || needsCheckedSetter || needsGetter || needsSetter) {
+      // Ignore needsCheckedSetter - that is handled below.
+      bool needsAccessor = (needsGetter || needsSetter);
+      // We need to output the fields for non-native classes so we can auto-
+      // generate the constructor.  For native classes there are no
+      // constructors, so we don't need the fields unless we are generating
+      // accessors at runtime.
+      if (!classIsNative || needsAccessor) {
+        // Emit correct commas.
         if (isFirstField) {
           isFirstField = false;
           if (!isAnythingOutput) {
@@ -863,13 +915,28 @@
         } else {
           buffer.add(",");
         }
-        buffer.add('$name');
+        int flag = 0;
+        if (!needsAccessor) {
+          // Emit field for constructor generation.
+          assert(!classIsNative);
+          buffer.add(name);
+        } else {
+          // Emit (possibly renaming) field name so we can add accessors at
+          // runtime.
+          buffer.add(accessorName);
+          if (name != accessorName) {
+            buffer.add(':$name');
+            // Only the native classes can have renaming accessors.
+            assert(classIsNative);
+            flag = RENAMING_FLAG;
+          }
+        }
         if (needsGetter && needsSetter) {
-          buffer.add(GETTER_SETTER_SUFFIX);
+          buffer.addCharCode(GETTER_SETTER_CODE + flag);
         } else if (needsGetter) {
-          buffer.add(GETTER_SUFFIX);
+          buffer.addCharCode(GETTER_CODE + flag);
         } else if (needsSetter) {
-          buffer.add(SETTER_SUFFIX);
+          buffer.addCharCode(SETTER_CODE + flag);
         }
       }
     });
@@ -887,7 +954,7 @@
                                bool emitLeadingComma) {
     emitComma() {
       if (emitLeadingComma) {
-        buffer.add(",\n ");
+        buffer.add(",\n$_");
       } else {
         emitLeadingComma = true;
       }
@@ -895,48 +962,28 @@
 
     visitClassFields(classElement, (Element member,
                                     String name,
+                                    String accessorName,
                                     bool needsGetter,
                                     bool needsSetter,
                                     bool needsCheckedSetter) {
-          if (name == null) throw 123;
-      if (getterAndSetterCanBeImplementedByFieldSpec(
-          member, name, needsGetter, needsSetter)) {
-        needsGetter = false;
-        needsSetter = false;
-      }
-      if (needsGetter) {
-        emitComma();
-        generateGetter(member, name, buffer);
-      }
-      if (needsSetter) {
-        emitComma();
-        generateSetter(member, name, buffer);
-      }
       if (needsCheckedSetter) {
         assert(!needsSetter);
         emitComma();
-        generateCheckedSetter(member, name, buffer);
+        generateCheckedSetter(member, name, accessorName, buffer);
+      }
+      if (!getterAndSetterCanBeImplementedByFieldSpec) {
+        if (needsGetter) {
+          emitComma();
+          generateGetter(member, name, accessorName, buffer);
+        }
+        if (needsSetter) {
+          emitComma();
+          generateSetter(member, name, accessorName, buffer);
+        }
       }
     });
   }
 
-  bool getterAndSetterCanBeImplementedByFieldSpec(Element member,
-      String name,
-      bool needsGetter,
-      bool needsSetter) {
-    if (needsGetter) {
-      if (namer.getterName(member.getLibrary(), member.name) != 'get\$$name') {
-        return false;
-      }
-    }
-    if (needsSetter) {
-      if (namer.setterName(member.getLibrary(), member.name) != 'set\$$name') {
-        return false;
-      }
-    }
-    return true;
-  }
-
   /**
    * Documentation wanted -- johnniwinther
    *
@@ -962,18 +1009,21 @@
       superName = namer.getName(superclass);
     }
 
-    buffer.add('$classesCollector.$className = {');
+    buffer.add('$classesCollector.$className$_=$_{');
     emitClassConstructor(classElement, buffer);
+    emitSuper(superName, buffer);
     emitClassFields(classElement, buffer, false,
-                    superClass: superName, isNative: false);
+                    superClass: superName, classIsNative: false);
     // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'.
     // That does currently not work because the native classes have a different
     // syntax.
     emitClassGettersSetters(classElement, buffer, true);
     emitInstanceMembers(classElement, buffer, true);
-    buffer.add('\n};\n\n');
+    buffer.add('$n}$N$n');
   }
 
+  bool get getterAndSetterCanBeImplementedByFieldSpec => true;
+
   void emitInterceptorMethods(
       void defineInstanceMember(String name, StringBuffer memberBuffer)) {
     JavaScriptBackend backend = compiler.backend;
@@ -1002,7 +1052,7 @@
           arguments.add(new js.VariableUse(argName));
         }
       }
-      js.Fun function = 
+      js.Fun function =
           new js.Fun(parameters,
               new js.Block(
                   <js.Statement>[
@@ -1023,16 +1073,30 @@
    * super class because they will be inherited at runtime.
    */
   void generateIsTestsOn(ClassElement cls,
-                         void emitIsTest(ClassElement element)) {
+                         void emitIsTest(Element element)) {
     if (checkedClasses.contains(cls)) {
       emitIsTest(cls);
     }
+
     Set<Element> generated = new Set<Element>();
     // A class that defines a [:call:] method implicitly implements
-    // [Function].
-    if (checkedClasses.contains(compiler.functionClass)
-        && cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME) != null) {
-      generateInterfacesIsTests(compiler.functionClass, emitIsTest, generated);
+    // [Function] and needs checks for all typedefs that are used in is-checks.
+    if (checkedClasses.contains(compiler.functionClass) ||
+        !checkedTypedefs.isEmpty) {
+      FunctionElement call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME);
+      if (call != null) {
+        generateInterfacesIsTests(compiler.functionClass,
+                                  emitIsTest,
+                                  generated);
+        FunctionType callType = call.computeType(compiler);
+        for (TypedefElement typedef in checkedTypedefs) {
+          FunctionType typedefType =
+              typedef.computeType(compiler).unalias(compiler);
+          if (compiler.types.isSubtype(callType, typedefType)) {
+            emitIsTest(typedef);
+          }
+        }
+      }
     }
     for (DartType interfaceType in cls.interfaces) {
       generateInterfacesIsTests(interfaceType.element, emitIsTest, generated);
@@ -1068,14 +1132,59 @@
     }
   }
 
+  /**
+   * Return a function that returns true if its argument is a class
+   * that needs to be emitted.
+   */
+  Function computeClassFilter() {
+    Set<ClassElement> unneededClasses = new Set<ClassElement>();
+    // The [Bool] class is not marked as abstract, but has a factory
+    // constructor that always throws. We never need to emit it.
+    unneededClasses.add(compiler.boolClass);
+
+    JavaScriptBackend backend = compiler.backend;
+
+    // Go over specialized interceptors and then constants to know which
+    // interceptors are needed.
+    Set<ClassElement> needed = new Set<ClassElement>();
+    backend.specializedGetInterceptors.forEach(
+        (_, Collection<ClassElement> elements) {
+          needed.addAll(elements);
+        }
+    );
+
+    ConstantHandler handler = compiler.constantHandler;
+    List<Constant> constants = handler.getConstantsForEmission();
+    for (Constant constant in constants) {
+      if (constant is ConstructedConstant) {
+        Element element = constant.computeType(compiler).element;
+        if (backend.isInterceptorClass(element)) {
+          needed.add(element);
+        }
+      }
+    }
+
+    // Add unneeded interceptors to the [unneededClasses] set.
+    for (ClassElement interceptor in backend.interceptedClasses.keys) {
+      if (!needed.contains(interceptor)) {
+        unneededClasses.add(interceptor);
+      }
+    }
+
+    return (ClassElement cls) => !unneededClasses.contains(cls);
+  }
+
   void emitClasses(CodeBuffer buffer) {
     // Compute the required type checks to know which classes need a
     // 'is$' method.
     computeRequiredTypeChecks();
+
     Set<ClassElement> instantiatedClasses =
-        compiler.codegenWorld.instantiatedClasses;
+        compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter());
+
     Set<ClassElement> neededClasses =
         new Set<ClassElement>.from(instantiatedClasses);
+
     for (ClassElement element in instantiatedClasses) {
       for (ClassElement superclass = element.superclass;
            superclass != null;
@@ -1124,9 +1233,9 @@
 
   void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) {
     if (needsDefineClass) {
-      buffer.add("$finishClassesName($classesCollector);\n");
+      buffer.add("$finishClassesName($classesCollector)$N");
       // Reset the map.
-      buffer.add("$classesCollector = {};\n");
+      buffer.add("$classesCollector$_=$_{}$N");
     }
   }
 
@@ -1135,9 +1244,9 @@
                                    CodeBuffer functionBuffer,
                                    String functionNamer(Element element)) {
     String functionName = functionNamer(element);
-    buffer.add('$isolateProperties.$functionName = ');
+    buffer.add('$isolateProperties.$functionName$_=$_');
     buffer.add(functionBuffer);
-    buffer.add(';\n\n');
+    buffer.add('$N$n');
   }
   void emitStaticFunctionsWithNamer(CodeBuffer buffer,
                                     Map<Element, CodeBuffer> generatedCode,
@@ -1168,30 +1277,28 @@
       // create a fake element with the correct name.
       // Note: the callElement will not have any enclosingElement.
       FunctionElement callElement =
-          new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element);
+          new ClosureInvocationElement(namer.closureInvocationSelectorName,
+                                       element);
       String staticName = namer.getName(element);
       String invocationName = namer.instanceMethodName(callElement);
       String fieldAccess = '$isolateProperties.$staticName';
-      buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n");
+      buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N");
       addParameterStubs(callElement, (String name, CodeBuffer value) {
-        buffer.add('$fieldAccess.$name = $value;\n');
+        buffer.add('$fieldAccess.$name$_=$_$value$N');
       });
       // If a static function is used as a closure we need to add its name
       // in case it is used in spawnFunction.
       String fieldName = namer.STATIC_CLOSURE_NAME_NAME;
-      buffer.add('$fieldAccess.$fieldName = "$staticName";\n');
+      buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N');
     }
   }
 
   void emitBoundClosureClassHeader(String mangledName,
                                    String superName,
-                                   String extraArgument,
+                                   List<String> fieldNames,
                                    CodeBuffer buffer) {
-    extraArgument = extraArgument.isEmpty ? '' : ",$extraArgument";
-    buffer.add("""
-$classesCollector.$mangledName = {'':
-\"$superName;self$extraArgument,target\",
-""");
+    buffer.add('$classesCollector.$mangledName$_=$_'
+               '{"":"$superName;${Strings.join(fieldNames,',')}",');
   }
 
   /**
@@ -1227,25 +1334,24 @@
     int parameterCount = member.parameterCount(compiler);
 
     Map<int, String> cache;
-    String extraArg;
-    String extraArgWithoutComma;
-    bool hasExtraArgument = false;
-    // Methods on foreign classes take an extra parameter, which is
-    // the actual receiver of the call.
+    String extraArg = null;
+    // Methods on interceptor classes take an extra parameter, which is the
+    // actual receiver of the call.
     JavaScriptBackend backend = compiler.backend;
-    if (backend.isInterceptorClass(member.getEnclosingClass())) {
-      hasExtraArgument = true;
+    bool inInterceptor = backend.isInterceptorClass(member.getEnclosingClass());
+    if (inInterceptor) {
       cache = interceptorClosureCache;
-      extraArg = 'receiver, ';
-      extraArgWithoutComma = 'receiver';
+      extraArg = 'receiver';
     } else {
       cache = boundClosureCache;
-      extraArg = '';
-      extraArgWithoutComma = '';
     }
+    List<String> fieldNames = compiler.enableMinification
+        ? inInterceptor ? const ['a', 'b', 'c']
+                        : const ['a', 'b']
+        : inInterceptor ? const ['self', 'target', 'receiver']
+                        : const ['self', 'target'];
 
-    String closureClass =
-        hasOptionalParameters ? null : cache[parameterCount];
+    String closureClass = hasOptionalParameters ? null : cache[parameterCount];
     if (closureClass == null) {
       // Either the class was not cached yet, or there are optional parameters.
       // Create a new closure class.
@@ -1259,33 +1365,45 @@
       // Define the constructor with a name so that Object.toString can
       // find the class name of the closure class.
       emitBoundClosureClassHeader(
-          mangledName, superName, extraArgWithoutComma, boundClosureBuffer);
+          mangledName, superName, fieldNames, boundClosureBuffer);
       // Now add the methods on the closure class. The instance method does not
       // have the correct name. Since [addParameterStubs] use the name to create
       // its stubs we simply create a fake element with the correct name.
       // Note: the callElement will not have any enclosingElement.
       FunctionElement callElement =
-          new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member);
-      
+          new ClosureInvocationElement(namer.closureInvocationSelectorName,
+                                       member);
+
       String invocationName = namer.instanceMethodName(callElement);
-      List<String> arguments = new List<String>(parameterCount);
-      for (int i = 0; i < parameterCount; i++) {
-        arguments[i] = "p$i";
+
+      List<js.Parameter> parameters = <js.Parameter>[];
+      List<js.Expression> arguments = <js.Expression>[];
+      if (inInterceptor) {
+        arguments.add(new js.This().dot(fieldNames[2]));
       }
-      String joinedArgs = Strings.join(arguments, ", ");
+      for (int i = 0; i < parameterCount; i++) {
+        String name = 'p$i';
+        parameters.add(new js.Parameter(name));
+        arguments.add(new js.VariableUse(name));
+      }
+
+      js.Expression fun =
+          new js.Fun(parameters,
+              new js.Block(
+                  <js.Statement>[
+                      new js.Return(
+                          new js.PropertyAccess(
+                              new js.This().dot(fieldNames[0]),
+                              new js.This().dot(fieldNames[1]))
+                          .callWith(arguments))]));
+
       boundClosureBuffer.add(
-          "$invocationName: function($joinedArgs) {");
-      String callArgs = hasExtraArgument
-          ? joinedArgs.isEmpty
-              ? 'this.$extraArgWithoutComma'
-              : 'this.$extraArg$joinedArgs'
-          : joinedArgs;
-      boundClosureBuffer.add(" return this.self[this.target]($callArgs);");
-      boundClosureBuffer.add(" }");
+          '$_$invocationName:$_${js.prettyPrint(fun,compiler)}');
+
       addParameterStubs(callElement, (String stubName, CodeBuffer memberValue) {
-        boundClosureBuffer.add(',\n $stubName: $memberValue');
+        boundClosureBuffer.add(',\n$_$stubName:$_$memberValue');
       });
-      boundClosureBuffer.add("\n};\n");
+      boundClosureBuffer.add("$n}$N");
 
       closureClass = namer.isolateAccess(closureClassElement);
 
@@ -1298,9 +1416,27 @@
     // And finally the getter.
     String getterName = namer.getterName(member.getLibrary(), member.name);
     String targetName = namer.instanceMethodName(member);
+
+    List<js.Parameter> parameters = <js.Parameter>[];
+    List<js.Expression> arguments = <js.Expression>[];
+    arguments.add(new js.This());
+    arguments.add(new js.LiteralString("'$targetName'"));
+    if (inInterceptor) {
+      parameters.add(new js.Parameter(extraArg));
+      arguments.add(new js.VariableUse(extraArg));
+    }
+
+    js.Expression getterFunction =
+        new js.Fun(parameters,
+            new js.Block(
+                <js.Statement>[
+                    new js.Return(
+                        new js.New(
+                            new js.VariableUse(closureClass),
+                            arguments))]));
+
     CodeBuffer getterBuffer = new CodeBuffer();
-    getterBuffer.add("function($extraArgWithoutComma) "
-        "{ return new $closureClass(this, $extraArg'$targetName'); }");
+    getterBuffer.add(js.prettyPrint(getterFunction, compiler));
     defineInstanceMember(getterName, getterBuffer);
   }
 
@@ -1330,8 +1466,8 @@
                 ? <js.Expression>[new js.VariableUse(receiverArgumentName)]
                 : <js.Expression>[]);
       } else {
-        String fieldName = member.isNative()
-            ? member.nativeName()
+        String fieldName = member.hasFixedBackendName()
+            ? member.fixedBackendName()
             : namer.instanceFieldName(memberLibrary, member.name);
         return new js.VariableUse('this').dot(fieldName);
       }
@@ -1342,7 +1478,7 @@
         String invocationName =
             namer.instanceMethodInvocationName(memberLibrary, member.name,
                                                selector);
-        SourceString callName = Namer.CLOSURE_INVOCATION_NAME;
+        SourceString callName = namer.closureInvocationSelectorName;
         String closureCallName =
             namer.instanceMethodInvocationName(memberLibrary, callName,
                                                selector);
@@ -1388,7 +1524,7 @@
                     namer.getName(element)),
                 constantEmitter.referenceInInitializationContext(initialValue));
         buffer.add(js.prettyPrint(init, compiler));
-        buffer.add(';\n');
+        buffer.add('$N');
       });
     }
   }
@@ -1410,16 +1546,16 @@
         // closure that constructs the initial value.
         buffer.add("$lazyInitializerName(");
         buffer.add(isolateProperties);
-        buffer.add(", '");
+        buffer.add(",$_'");
         buffer.add(element.name.slowToString());
-        buffer.add("', '");
+        buffer.add("',$_'");
         buffer.add(namer.getName(element));
-        buffer.add("', '");
+        buffer.add("',$_'");
         buffer.add(namer.getLazyInitializerName(element));
-        buffer.add("', ");
+        buffer.add("',$_");
         buffer.add(code);
         emitLazyInitializedGetter(element, buffer);
-        buffer.add(");\n");
+        buffer.add(")$N");
       }
     }
   }
@@ -1454,12 +1590,12 @@
                   name),
               constantInitializerExpression(constant));
       buffer.add(js.prettyPrint(init, compiler));
-      buffer.add(';\n');
+      buffer.add('$N');
     }
   }
 
   void emitMakeConstantList(CodeBuffer buffer) {
-    buffer.add(namer.ISOLATE);
+    buffer.add(namer.isolateName);
     buffer.add(r'''.makeConstantList = function(list) {
   list.immutable$list = true;
   list.fixed$length = true;
@@ -1495,6 +1631,11 @@
     String noSuchMethodName = namer.publicInstanceMethodNameByArity(
         Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
 
+    Element createInvocationMirrorElement =
+        compiler.findHelper(const SourceString("createInvocationMirror"));
+    String createInvocationMirrorName =
+        namer.getName(createInvocationMirrorElement);
+
     // Keep track of the JavaScript names we've already added so we
     // do not introduce duplicates (bad for code size).
     Set<String> addedJsNames = new Set<String>();
@@ -1517,43 +1658,46 @@
       return result;
     }
 
-    CodeBuffer generateMethod(String methodName, Selector selector) {
+    js.Expression generateMethod(String jsName, Selector selector) {
       // Values match JSInvocationMirror in js-helper library.
-      const int METHOD = 0;
-      const int GETTER = 1;
-      const int SETTER = 2;
-      int type = METHOD;
-      if (selector.isGetter()) {
-        type = GETTER;
-        assert(methodName.startsWith("get:"));
-        methodName = methodName.substring(4);
-      } else if (selector.isSetter()) {
-        type = SETTER;
-        assert(methodName.startsWith("set:"));
-        methodName = "${methodName.substring(4)}=";
-      }
+      int type = selector.invocationMirrorKind;
+      String methodName = selector.invocationMirrorMemberName;
+      List<js.Parameter> parameters = <js.Parameter>[];
       CodeBuffer args = new CodeBuffer();
       for (int i = 0; i < selector.argumentCount; i++) {
-        if (i != 0) args.add(', ');
-        args.add('\$$i');
+        parameters.add(new js.Parameter('\$$i'));
       }
-      CodeBuffer argNames = new CodeBuffer();
-      List<SourceString> names = selector.getOrderedNamedArguments();
-      for (int i = 0; i < names.length; i++) {
-        if (i != 0) argNames.add(', ');
-        argNames.add('"');
-        argNames.add(names[i].slowToString());
-        argNames.add('"');
-      }
+
+      List<js.Expression> argNames =
+          selector.getOrderedNamedArguments().map((SourceString name) =>
+              new js.LiteralString('"${name.slowToString()}"'));
+
       String internalName = namer.instanceMethodInvocationName(
           selector.library, new SourceString(methodName), selector);
-      CodeBuffer buffer = new CodeBuffer();
-      buffer.add('function($args) {\n');
-      buffer.add('  return this.$noSuchMethodName('
-                     '\$.createInvocationMirror("$methodName", "$internalName",'
-                     ' $type, [$args], [$argNames]));\n');
-      buffer.add(' }');
-      return buffer;
+
+      String createInvocationMirror = namer.getName(
+          compiler.createInvocationMirrorElement);
+
+      js.Expression expression =
+          new js.This()
+          .dot(noSuchMethodName)
+          .callWith(
+              <js.Expression>[
+                  new js.VariableUse(namer.CURRENT_ISOLATE)
+                  .dot(createInvocationMirror)
+                  .callWith(
+                      <js.Expression>[
+                          new js.LiteralString('"$methodName"'),
+                          new js.LiteralString('"$internalName"'),
+                          new js.LiteralNumber('$type'),
+                          new js.ArrayInitializer.from(
+                              parameters.map((param) =>
+                                  new js.VariableUse(param.name))),
+                          new js.ArrayInitializer.from(argNames)])]);
+      js.Expression function =
+          new js.Fun(parameters,
+              new js.Block(<js.Statement>[new js.Return(expression)]));
+      return function;
     }
 
     void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) {
@@ -1573,13 +1717,17 @@
           // Selector.applies() method.
           if (element is AbstractFieldElement) {
             AbstractFieldElement field = element;
-            if (identical(selector.kind, SelectorKind.GETTER)) {
+            if (selector.isGetter()) {
               return field.getter != null;
-            } else if (identical(selector.kind, SelectorKind.SETTER)) {
+            } else if (selector.isSetter()) {
               return field.setter != null;
             } else {
               return false;
             }
+          } else if (element is VariableElement) {
+            if (selector.isSetter() && element.modifiers.isFinalOrConst()) {
+              return false;
+            }
           }
           return selector.applies(element, compiler);
         }
@@ -1639,28 +1787,11 @@
         // does not implement bar.
         Set<ClassElement> holders = noSuchMethodHoldersFor(receiverType);
         if (holders.every(hasMatchingMember)) continue;
-
-        String jsName = null;
-        String methodName = null;
-        String nameString = selector.name.slowToString();
-        if (selector.isGetter()) {
-          jsName = namer.getterName(selector.library, selector.name);
-          methodName = 'get:$nameString';
-        } else if (selector.isSetter()) {
-          jsName = namer.setterName(selector.library, selector.name);
-          methodName = 'set:$nameString';
-        } else if (selector.isCall()) {
-          jsName = namer.instanceMethodInvocationName(
-              selector.library, selector.name, selector);
-          methodName = nameString;
-        } else {
-          // We simply ignore selectors that do not need
-          // noSuchMethod handlers.
-          continue;
-        }
-
+        String jsName = namer.invocationMirrorInternalName(selector);
         if (!addedJsNames.contains(jsName)) {
-          CodeBuffer jsCode = generateMethod(methodName, selector);
+          js.Expression method = generateMethod(jsName, selector);
+          CodeBuffer jsCode = new CodeBuffer();
+          jsCode.add(js.prettyPrint(method, compiler));
           defineInstanceMember(jsName, jsCode);
           addedJsNames.add(jsName);
         }
@@ -1697,7 +1828,7 @@
 function \$static_init(){};
 
 function \$initGlobals(context) {
-  context.isolateStatics = new ${namer.ISOLATE}();
+  context.isolateStatics = new ${namer.isolateName}();
 }
 function \$setGlobals(context) {
   $currentIsolate = context.isolateStatics;
@@ -1712,22 +1843,26 @@
     if (compiler.isMockCompilation) return;
     Element main = compiler.mainApp.find(Compiler.MAIN);
     String mainCall = null;
-    if (compiler.isolateLibrary != null) {
+    if (compiler.isolateHelperLibrary != null) {
       Element isolateMain =
-        compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE);
+        compiler.isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE);
       mainCall = buildIsolateSetup(buffer, main, isolateMain);
     } else {
       mainCall = '${namer.isolateAccess(main)}()';
     }
-    buffer.add("""
+    if (!compiler.enableMinification) {
+      buffer.add("""
 
 //
 // BEGIN invoke [main].
 //
-if (typeof document != 'undefined' && document.readyState != 'complete') {
+""");
+    }
+    buffer.add("""
+if (typeof document !== 'undefined' && document.readyState !== 'complete') {
   document.addEventListener('readystatechange', function () {
     if (document.readyState == 'complete') {
-      if (typeof dartMainRunner == 'function') {
+      if (typeof dartMainRunner === 'function') {
         dartMainRunner(function() { ${mainCall}; });
       } else {
         ${mainCall};
@@ -1735,17 +1870,21 @@
     }
   }, false);
 } else {
-  if (typeof dartMainRunner == 'function') {
+  if (typeof dartMainRunner === 'function') {
     dartMainRunner(function() { ${mainCall}; });
   } else {
     ${mainCall};
   }
 }
+""");
+    if (!compiler.enableMinification) {
+      buffer.add("""
 //
 // END invoke [main].
 //
 
 """);
+    }
   }
 
   /**
@@ -1756,22 +1895,24 @@
     JavaScriptBackend backend = compiler.backend;
     assert(backend.isInterceptorClass(cls));
     if (cls == backend.jsBoolClass) {
-      buffer.add("if (typeof receiver == 'boolean')");
+      buffer.add("if$_(typeof receiver$_==$_'boolean')");
     } else if (cls == backend.jsIntClass) {
-      buffer.add("if (typeof receiver == 'number' "
-                 "&& Math.floor(receiver) == receiver)");
+      buffer.add("if$_(typeof receiver$_==$_'number'$_"
+                 "&&${_}Math.floor(receiver)$_==${_}receiver)");
     } else if (cls == backend.jsDoubleClass || cls == backend.jsNumberClass) {
-      buffer.add("if (typeof receiver == 'number')");
+      buffer.add("if$_(typeof receiver$_==$_'number')");
     } else if (cls == backend.jsArrayClass) {
-      buffer.add("if (receiver != null && receiver.constructor == Array)");
+      buffer.add("if$_(receiver$_!=${_}null$_&&$_"
+                 "receiver.constructor$_==${_}Array)");
     } else if (cls == backend.jsStringClass) {
-      buffer.add("if (typeof receiver == 'string')");
+      buffer.add("if$_(typeof receiver$_==$_'string')");
     } else if (cls == backend.jsNullClass) {
-      buffer.add("if (receiver == null)");
+      buffer.add("if$_(receiver$_==${_}null)");
     } else if (cls == backend.jsFunctionClass) {
-      buffer.add("if (typeof receiver == 'function')");
+      buffer.add("if$_(typeof receiver$_==$_'function')");
     }
-    buffer.add(' return ${namer.isolateAccess(cls)}.prototype;');
+    buffer.add('${_}return ${namer.isolateAccess(cls)}.prototype');
+    if (!compiler.enableMinification) buffer.add(';');
   }
 
   /**
@@ -1784,28 +1925,30 @@
     String objectName = namer.isolateAccess(backend.objectInterceptorClass);
     backend.specializedGetInterceptors.forEach(
         (String key, Collection<ClassElement> classes) {
-          buffer.add('$isolateProperties.$key = function(receiver) {');
+          buffer.add('$isolateProperties.$key$_=${_}function(receiver)$_{');
           for (ClassElement cls in classes) {
             if (compiler.codegenWorld.instantiatedClasses.contains(cls)) {
-              buffer.add('\n  ');
+              buffer.add('\n$_$_');
               emitInterceptorCheck(cls, buffer);
             }
           }
-          buffer.add('\n  return $objectName.prototype;\n};\n');
+          buffer.add('\n$_${_}return $objectName.prototype;$n}$N');
         });
   }
 
   String assembleProgram() {
     measure(() {
-      mainBuffer.add(HOOKS_API_USAGE);
-      mainBuffer.add('function ${namer.ISOLATE}() {}\n');
-      mainBuffer.add('init();\n\n');
+      mainBuffer.add(GENERATED_BY);
+      if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE);
+      mainBuffer.add('function ${namer.isolateName}()$_{}\n');
+      mainBuffer.add('init()$N$n');
       // Shorten the code by using "$$" as temporary.
       classesCollector = r"$$";
-      mainBuffer.add('var $classesCollector = {};\n');
+      mainBuffer.add('var $classesCollector$_=$_{}$N');
       // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
       isolateProperties = namer.CURRENT_ISOLATE;
-      mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n');
+      mainBuffer.add(
+          'var $isolateProperties$_=$_$isolatePropertiesName$N');
       emitClasses(mainBuffer);
       mainBuffer.add(boundClosureBuffer);
       // Clear the buffer, so that we can reuse it for the native classes.
@@ -1825,7 +1968,7 @@
       isolateProperties = isolatePropertiesName;
       // The following code should not use the short-hand for the
       // initialStatics.
-      mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n');
+      mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N');
       mainBuffer.add(boundClosureBuffer);
       emitFinishClassesInvocationIfNecessary(mainBuffer);
       // After this assignment we will produce invalid JavaScript code if we use
@@ -1833,13 +1976,13 @@
       classesCollector = 'classesCollector should not be used from now on';
 
       emitFinishIsolateConstructorInvocation(mainBuffer);
-      mainBuffer.add(
-        'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n');
+      mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_='
+                     '${_}new ${namer.isolateName}()$N');
 
       nativeEmitter.assembleCode(mainBuffer);
       emitMain(mainBuffer);
-      mainBuffer.add('function init() {\n');
-      mainBuffer.add('$isolateProperties = {};\n');
+      mainBuffer.add('function init()$_{\n');
+      mainBuffer.add('$isolateProperties$_=$_{}$N');
       addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer);
       addLazyInitializerFunctionIfNecessary(mainBuffer);
       emitFinishIsolateConstructor(mainBuffer);
@@ -1868,8 +2011,10 @@
 
 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition);
 
-const String HOOKS_API_USAGE = """
+const String GENERATED_BY = """
 // Generated by dart2js, the Dart to JavaScript compiler.
+""";
+const String HOOKS_API_USAGE = """
 // The code supports the following hooks:
 // dartPrint(message)   - if this function is defined it is called
 //                        instead of the Dart [print] method.
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
index 0b6c0f5..e0d1fba 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
@@ -39,7 +39,7 @@
     // isolateProperties themselves.
     return """
 function(oldIsolate) {
-  var isolateProperties = oldIsolate.${namer.ISOLATE_PROPERTIES};
+  var isolateProperties = oldIsolate.${namer.isolatePropertiesName};
   function Isolate() {
     for (var staticName in isolateProperties) {
       if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) {
@@ -54,7 +54,7 @@
   }
   Isolate.prototype = oldIsolate.prototype;
   Isolate.prototype.constructor = Isolate;
-  Isolate.${namer.ISOLATE_PROPERTIES} = isolateProperties;
+  Isolate.${namer.isolatePropertiesName} = isolateProperties;
   return Isolate;
 }""";
   }
@@ -71,29 +71,27 @@
     buffer.add(', function() { return $isolate.${namer.getName(element)}; }');
   }
 
+  js.Expression buildConstructor(String mangledName, List<String> fieldNames) {
+    return new js.NamedFunction(
+        new js.VariableDeclaration(mangledName),
+        new js.Fun(
+            fieldNames.map((fieldName) => new js.Parameter(fieldName)),
+            new js.Block(
+                fieldNames.map((fieldName) =>
+                    new js.ExpressionStatement(
+                        new js.Assignment(
+                            new js.This().dot(fieldName),
+                            new js.VariableUse(fieldName)))))));
+  }
+
   void emitBoundClosureClassHeader(String mangledName,
                                    String superName,
-                                   String extraArgument,
+                                   List<String> fieldNames,
                                    CodeBuffer buffer) {
-    if (!extraArgument.isEmpty) {
-      buffer.add("""
-$classesCollector.$mangledName = {'': function $mangledName(
-    self, $extraArgument, target) {
-  this.self = self;
-  this.$extraArgument = $extraArgument,
-  this.target = target;
- },
- 'super': '$superName',
-""");
-    } else {
-      buffer.add("""
-$classesCollector.$mangledName = {'': function $mangledName(self, target) {
-  this.self = self;
-  this.target = target;
- },
- 'super': '$superName',
-""");
-    }
+    buffer.add("$classesCollector.$mangledName = {'': ");
+    buffer.add(
+        js.prettyPrint(buildConstructor(mangledName, fieldNames), compiler));
+    buffer.add(",\n 'super': '$superName',\n");
   }
 
   void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) {
@@ -108,42 +106,31 @@
     List<String> fields = <String>[];
     visitClassFields(classElement, (Element member,
                                     String name,
+                                    String accessorName,
                                     bool needsGetter,
                                     bool needsSetter,
                                     bool needsCheckedSetter) {
       fields.add(name);
     });
-
-    List<String> argumentNames = fields;
-    if (fields.length < ($z - $a)) {
-      argumentNames = new List<String>(fields.length);
-      for (int i = 0; i < fields.length; i++) {
-        argumentNames[i] = new String.fromCharCodes([$a + i]);
-      }
-    }
     String constructorName = namer.safeName(classElement.name.slowToString());
-    // Generate the constructor.
-    buffer.add("'': function $constructorName(");
-    buffer.add(Strings.join(argumentNames, ", "));
-    buffer.add(") {\n");
-    for (int i = 0; i < fields.length; i++) {
-      buffer.add("  this.${fields[i]} = ${argumentNames[i]};\n");
+    buffer.add("'': ");
+    buffer.add(
+        js.prettyPrint(buildConstructor(constructorName, fields), compiler));
+  }
+
+  void emitSuper(String superName, CodeBuffer buffer) {
+    if (superName != '') {
+      buffer.add(",\n 'super': '$superName'");
     }
-    buffer.add(' }');
   }
 
   void emitClassFields(ClassElement classElement,
                        CodeBuffer buffer,
                        bool emitEndingComma,
                        { String superClass: "",
-                         bool isNative: false}) {
+                         bool classIsNative: false}) {
     if (emitEndingComma) buffer.add(', ');
   }
 
-  bool getterAndSetterCanBeImplementedByFieldSpec(Element member,
-                                                  String name,
-                                                  bool needsGetter,
-                                                  bool needsSetter) {
-    return false;
-  }
+  bool get getterAndSetterCanBeImplementedByFieldSpec => false;
 }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
index 1f2106e..a25b024 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -23,6 +23,7 @@
 part 'constant_system_javascript.dart';
 part 'emitter.dart';
 part 'emitter_no_eval.dart';
+part 'minify_namer.dart';
 part 'namer.dart';
 part 'native_emitter.dart';
 part 'runtime_types.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
new file mode 100644
index 0000000..5d176c1
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of js_backend;
+
+/**
+ * Assigns JavaScript identifiers to Dart variables, class-names and members.
+ */
+class MinifyNamer extends Namer {
+  MinifyNamer(Compiler compiler) : super(compiler);
+
+  String get isolateName => 'I';
+  String get isolatePropertiesName => 'p';
+  bool get shouldMinify => true;
+
+  const ALPHABET_CHARACTERS = 52;  // a-zA-Z.
+  const ALPHANUMERIC_CHARACTERS = 62;  // a-zA-Z0-9.
+
+  // You can pass an invalid identifier to this and unlike its non-minifying
+  // counterpart it will never return the proposedName as the new fresh name.
+  String getFreshName(String proposedName, Set<String> usedNames) {
+    var freshName = _getUnusedName(proposedName, usedNames);
+    usedNames.add(freshName);
+    return freshName;
+  }
+
+  SourceString getClosureVariableName(SourceString name, int id) {
+    if (id < ALPHABET_CHARACTERS) {
+      return new SourceString(new String.fromCharCodes([_letterNumber(id)]));
+    }
+    return new SourceString("${getMappedInstanceName('closure')}_$id");
+  }
+
+  // This gets a minified name based on a hash of the proposed name.  This
+  // is slightly less efficient than just getting the next name in a series,
+  // but it means that small changes in the input program will give smallish
+  // changes in the output, which can be useful for diffing etc.
+  String _getUnusedName(String proposedName, Set<String> usedNames) {
+    // Try single-character names with characters that occur in the
+    // input.
+    for (int i = 0; i < proposedName.length; i++) {
+      String candidate = proposedName[i];
+      int code = candidate.charCodeAt(0);
+      if (code < $A) continue;
+      if (code > $z) continue;
+      if (code > $Z && code < $a) continue;
+      if (!usedNames.contains(candidate)) return candidate;
+    }
+
+    int hash = _calculateHash(proposedName);
+    // Avoid very small hashes that won't try many names.
+    hash = hash < 1000 ? hash * 314159 : hash;  // Yes, it's prime.
+
+    // Try other n-character names based on the hash.  We try one to three
+    // character identifiers.  For each length we try around 10 different names
+    // in a predictable order determined by the proposed name.  This is in order
+    // to make the renamer stable: small changes in the input should nornally
+    // result in relatively small changes in the output.
+    for (var n = 1; n <= 3; n++) {
+      int h = hash;
+      while (h > 10) {
+        var codes = <int>[_letterNumber(h)];
+        int h2 = h ~/ ALPHABET_CHARACTERS;
+        for (var i = 1; i < n; i++) {
+          codes.add(_alphaNumericNumber(h2));
+          h2 ~/= ALPHANUMERIC_CHARACTERS;
+        }
+        final candidate = new String.fromCharCodes(codes);
+        if (!usedNames.contains(candidate) && !jsReserved.contains(candidate)) {
+          return candidate;
+        }
+        // Try again with a slightly different hash.  After around 10 turns
+        // around this loop h is zero and we try a longer name.
+        h ~/= 7;
+      }
+    }
+
+    // If we can't find a hash based name in the three-letter space, then base
+    // the name on a letter and a counter.
+    var startLetter = new String.fromCharCodes([_letterNumber(hash)]);
+    var i = 0;
+    while (usedNames.contains("$startLetter$i")) {
+      i++;
+    }
+    return "$startLetter$i";
+  }
+
+  int _calculateHash(String name) {
+    int h = 0;
+    for (int i = 0; i < name.length; i++) {
+      h += name.charCodeAt(i);
+      h &= 0xffffffff;
+      h += h << 10;
+      h &= 0xffffffff;
+      h ^= h >> 6;
+      h &= 0xffffffff;
+    }
+    return h;
+  }
+
+  int _letterNumber(int x) {
+    if (x >= ALPHABET_CHARACTERS) x %= ALPHABET_CHARACTERS;
+    if (x < 26) return $a + x;
+    return $A + x - 26;
+  }
+
+  int _alphaNumericNumber(int x) {
+    if (x >= ALPHANUMERIC_CHARACTERS) x %= ALPHANUMERIC_CHARACTERS;
+    if (x < 26) return $a + x;
+    if (x < 52) return $A + x - 26;
+    return $0 + x - 52;
+  }
+
+}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index c4888b2..ba55f77 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -7,9 +7,7 @@
 /**
  * Assigns JavaScript identifiers to Dart variables, class-names and members.
  */
-class Namer {
-  final Compiler compiler;
-
+class Namer implements ClosureNamer {
   static Set<String> _jsReserved = null;
   Set<String> get jsReserved {
     if (_jsReserved == null) {
@@ -20,15 +18,22 @@
     return _jsReserved;
   }
 
+  final String CURRENT_ISOLATE = r'$';
+
   /**
    * Map from top-level or static elements to their unique identifiers provided
    * by [getName].
    *
    * Invariant: Keys must be declaration elements.
    */
+  final Compiler compiler;
   final Map<Element, String> globals;
-  final Map<String, int> usedGlobals;
   final Map<String, LibraryElement> shortPrivateNameOwners;
+  final Set<String> usedGlobalNames;
+  final Set<String> usedInstanceNames;
+  final Map<String, String> instanceNameMap;
+  final Map<String, String> globalNameMap;
+  final Map<String, int> popularNameCounters;
 
   /**
    * A cache of names used for bailout methods. We make sure two
@@ -45,22 +50,27 @@
 
   Namer(this.compiler)
       : globals = new Map<Element, String>(),
-        usedGlobals = new Map<String, int>(),
         shortPrivateNameOwners = new Map<String, LibraryElement>(),
         bailoutNames = new Map<Element, String>(),
         usedBailoutInstanceNames = new Set<String>(),
-        constantNames = new Map<Constant, String>();
+        usedGlobalNames = new Set<String>(),
+        usedInstanceNames = new Set<String>(),
+        instanceNameMap = new Map<String, String>(),
+        globalNameMap = new Map<String, String>(),
+        constantNames = new Map<Constant, String>(),
+        popularNameCounters = new Map<String, int>();
 
-  final String CURRENT_ISOLATE = r'$';
-  final String ISOLATE = 'Isolate';
-  final String ISOLATE_PROPERTIES = r"$isolateProperties";
+  String get isolateName => 'Isolate';
+  String get isolatePropertiesName => r'$isolateProperties';
   /**
    * Some closures must contain their name. The name is stored in
    * [STATIC_CLOSURE_NAME_NAME].
    */
-  final String STATIC_CLOSURE_NAME_NAME = r'$name';
-  static const SourceString CLOSURE_INVOCATION_NAME =
-      Compiler.CALL_OPERATOR_NAME;
+  String get STATIC_CLOSURE_NAME_NAME => r'$name';
+  SourceString get closureInvocationSelectorName => Compiler.CALL_OPERATOR_NAME;
+  bool get shouldMinify => false;
+
+  bool isReserved(String name) => name == isolateName;
 
   String constantName(Constant constant) {
     // In the current implementation it doesn't make sense to give names to
@@ -69,15 +79,28 @@
     assert(!constant.isFunction());
     String result = constantNames[constant];
     if (result == null) {
-      result = getFreshGlobalName("CTC");
+      String longName;
+      if (shouldMinify) {
+        if (constant.isString()) {
+          StringConstant stringConstant = constant;
+          // The minifier always constructs a new name, using the argument as
+          // input to its hashing algorithm.  The given name does not need to be
+          // valid.
+          longName = stringConstant.value.slowToString();
+        } else {
+          longName = "C";
+        }
+      } else {
+        longName = "CONSTANT";
+      }
+      result = getFreshName(longName, usedGlobalNames);
       constantNames[constant] = result;
     }
     return result;
   }
 
   String closureInvocationName(Selector selector) {
-    // TODO(floitsch): mangle, while not conflicting with instance names.
-    return instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME,
+    return instanceMethodInvocationName(null, closureInvocationSelectorName,
                                         selector);
   }
 
@@ -104,25 +127,32 @@
    * mangles the [name] so that each library has a unique name.
    */
   String privateName(LibraryElement lib, SourceString name) {
+    String result;
     if (name.isPrivate()) {
       String nameString = name.slowToString();
       // The first library asking for a short private name wins.
-      LibraryElement owner =
+      LibraryElement owner = shouldMinify ?
+          lib :
           shortPrivateNameOwners.putIfAbsent(nameString, () => lib);
       // If a private name could clash with a mangled private name we don't
       // use the short name. For example a private name "_lib3_foo" would
       // clash with "_foo" from "lib3".
-      if (identical(owner, lib) && !nameString.startsWith('_$LIBRARY_PREFIX')) {
-        return nameString;
+      if (owner == lib &&
+          !nameString.startsWith('_$LIBRARY_PREFIX') &&
+          !shouldMinify) {
+        result = nameString;
+      } else {
+        String libName = getName(lib);
+        // If a library name does not start with the [LIBRARY_PREFIX] then our
+        // assumptions about clashing with mangled private members do not hold.
+        assert(shouldMinify || libName.startsWith(LIBRARY_PREFIX));
+        // TODO(erikcorry): Fix this with other manglings to avoid clashes.
+        result = '_lib$libName\$$nameString';
       }
-      String libName = getName(lib);
-      // If a library name does not start with the [LIBRARY_PREFIX] then our
-      // assumptions about clashing with mangled private members do not hold.
-      assert(libName.startsWith(LIBRARY_PREFIX));
-      return '_$libName$nameString';
     } else {
-      return name.slowToString();
+      result = name.slowToString();
     }
+    return result;
   }
 
   String instanceMethodName(FunctionElement element) {
@@ -135,21 +165,27 @@
     FunctionSignature signature = element.computeSignature(compiler);
     String methodName =
         '${privateName(lib, name)}\$${signature.parameterCount}';
-    if (!signature.optionalParametersAreNamed) {
-      return methodName;
-    } else if (!signature.optionalParameters.isEmpty) {
+    if (signature.optionalParametersAreNamed &&
+        !signature.optionalParameters.isEmpty) {
       StringBuffer buffer = new StringBuffer();
       signature.orderedOptionalParameters.forEach((Element element) {
         buffer.add('\$${JsNames.getValid(element.name.slowToString())}');
       });
-      return '$methodName$buffer';
+      methodName = '$methodName$buffer';
     }
+    if (name == closureInvocationSelectorName) return methodName;
+    return getMappedInstanceName(methodName);
   }
 
   String publicInstanceMethodNameByArity(SourceString name, int arity) {
     name = Elements.operatorNameToIdentifier(name);
     assert(!name.isPrivate());
-    return '${name.slowToString()}\$$arity';
+    var base = name.slowToString();
+    // We don't mangle the closure invoking function name because it is
+    // generated in by string concatenation applyFunction from js_helper.dart.
+    var proposedName = '$base\$$arity';
+    if (base == closureInvocationSelectorName) return proposedName;
+    return getMappedInstanceName(proposedName);
   }
 
   String instanceMethodInvocationName(LibraryElement lib, SourceString name,
@@ -162,59 +198,126 @@
       buffer.add(r'$');
       argumentName.printOn(buffer);
     }
-    return '${privateName(lib, name)}\$${selector.argumentCount}$buffer';
+    if (name == closureInvocationSelectorName) {
+    // We don't mangle the closure invoking function name because it is
+    // generated in by string concatenation applyFunction from js_helper.dart.
+      return '$closureInvocationSelectorName\$${selector.argumentCount}$buffer';
+    }
+    return getMappedInstanceName(
+        '${privateName(lib, name)}\$${selector.argumentCount}$buffer');
+  }
+
+  /**
+   * Returns the internal name used for an invocation mirror of this selector.
+   */
+  String invocationMirrorInternalName(Selector selector) {
+    if (selector.isGetter()) {
+      return getterName(selector.library, selector.name);
+    } else if (selector.isSetter()) {
+      return setterName(selector.library, selector.name);
+    } else {
+      return instanceMethodInvocationName(
+          selector.library, selector.name, selector);
+    }
   }
 
   String instanceFieldName(LibraryElement libraryElement, SourceString name) {
     String proposedName = privateName(libraryElement, name);
-    return safeName(proposedName);
+    return getMappedInstanceName(proposedName);
   }
 
+  // Construct a new name for the element based on the library and class it is
+  // in.  The name here is not important, we just need to make sure it is
+  // unique.  If we are minifying, we actually construct the name from the
+  // minified versions of the class and instance names, but the result is
+  // minified once again, so that is not visible in the end result.
   String shadowedFieldName(Element fieldElement) {
+    // Check for following situation: Native field ${fieldElement.name} has
+    // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this
+    // name.  We normally handle that by renaming the superclass field, but we
+    // can't do that because native fields have fixed JSNames.  In practice
+    // this can't happen because we can't inherit from native classes.
+    assert (!fieldElement.hasFixedBackendName());
+
     ClassElement cls = fieldElement.getEnclosingClass();
     LibraryElement libraryElement = fieldElement.getLibrary();
     String libName = getName(libraryElement);
     String clsName = getName(cls);
     String instanceName = instanceFieldName(libraryElement, fieldElement.name);
-    return safeName('$libName\$$clsName\$$instanceName');
+    return getMappedInstanceName('$libName\$$clsName\$$instanceName');
   }
 
   String setterName(LibraryElement lib, SourceString name) {
     // We dynamically create setters from the field-name. The setter name must
     // therefore be derived from the instance field-name.
-    String fieldName = safeName(privateName(lib, name));
+    String fieldName = getMappedInstanceName(privateName(lib, name));
     return 'set\$$fieldName';
   }
 
+  String setterNameFromAccessorName(String name) {
+    // We dynamically create setters from the field-name. The setter name must
+    // therefore be derived from the instance field-name.
+    return 'set\$$name';
+  }
+
   String publicGetterName(SourceString name) {
     // We dynamically create getters from the field-name. The getter name must
     // therefore be derived from the instance field-name.
-    String fieldName = safeName(name.slowToString());
+    String fieldName = getMappedInstanceName(name.slowToString());
     return 'get\$$fieldName';
   }
 
+  String getterNameFromAccessorName(String name) {
+    // We dynamically create getters from the field-name. The getter name must
+    // therefore be derived from the instance field-name.
+    return 'get\$$name';
+  }
+
   String getterName(LibraryElement lib, SourceString name) {
     // We dynamically create getters from the field-name. The getter name must
     // therefore be derived from the instance field-name.
-    String fieldName = safeName(privateName(lib, name));
+    String fieldName = getMappedInstanceName(privateName(lib, name));
     return 'get\$$fieldName';
   }
 
-  String getFreshGlobalName(String proposedName) {
-    String name = proposedName;
-    int count = usedGlobals[name];
-    if (count != null) {
-      // Not the first time we see this name. Append a number to make it unique.
-      do {
-        name = '$proposedName${count++}';
-      } while (usedGlobals[name] != null);
-      // Record the count in case we see this name later. We
-      // frequently see names multiple times, as all our closures use
-      // the same name for their class.
-      usedGlobals[proposedName] = count;
+  String getMappedGlobalName(String proposedName) {
+    var newName = globalNameMap[proposedName];
+    if (newName == null) {
+      newName = getFreshName(proposedName, usedGlobalNames);
+      globalNameMap[proposedName] = newName;
     }
-    usedGlobals[name] = 0;
-    return name;
+    return newName;
+  }
+
+  String getMappedInstanceName(String proposedName) {
+    var newName = instanceNameMap[proposedName];
+    if (newName == null) {
+      newName = getFreshName(proposedName, usedInstanceNames);
+      instanceNameMap[proposedName] = newName;
+    }
+    return newName;
+  }
+
+  String getFreshName(String proposedName, Set<String> usedNames) {
+    var candidate;
+    proposedName = safeName(proposedName);
+    if (!usedNames.contains(proposedName)) {
+      candidate = proposedName;
+    } else {
+      var counter = popularNameCounters[proposedName];
+      var i = counter == null ? 0 : counter;
+      while (usedNames.contains("$proposedName$i")) {
+        i++;
+      }
+      popularNameCounters[proposedName] = i + 1;
+      candidate = "$proposedName$i";
+    }
+    usedNames.add(candidate);
+    return candidate;
+  }
+
+  SourceString getClosureVariableName(SourceString name, int id) {
+    return new SourceString("${name.slowToString()}_$id");
   }
 
   static const String LIBRARY_PREFIX = "lib";
@@ -247,29 +350,38 @@
     } else {
       name = element.name.slowToString();
     }
-    return safeName(name);
+    return name;
   }
 
   String getSpecializedName(Element element, Collection<ClassElement> classes) {
+    // This gets the minified name, but it doesn't really make much difference.
+    // The important thing is that it is a unique name.
     StringBuffer buffer = new StringBuffer('${getName(element)}\$');
     for (ClassElement cls in classes) {
       buffer.add(getName(cls));
     }
-    return safeName(buffer.toString());
+    return getMappedGlobalName(buffer.toString());
   }
 
   String getBailoutName(Element element) {
     String name = bailoutNames[element];
     if (name != null) return name;
     bool global = !element.isInstanceMember();
+    // Despite the name of the variable, this gets the minified name when we
+    // are minifying, but it doesn't really make much difference.  The
+    // important thing is that it is a unique name.  We add $bailout and, if we
+    // are minifying, we minify the minified name and '$bailout'.
     String unminifiedName = '${getName(element)}\$bailout';
-    name = unminifiedName;
-    if (!global) {
+    if (global) {
+      name = getMappedGlobalName(unminifiedName);
+    } else {
+      name = unminifiedName;
       int i = 0;
       while (usedBailoutInstanceNames.contains(name)) {
         name = '$unminifiedName${i++}';
       }
       usedBailoutInstanceNames.add(name);
+      name = getMappedInstanceName(name);
     }
     bailoutNames[element] = name;
     return name;
@@ -307,21 +419,30 @@
 
       String guess = _computeGuess(element);
       ElementKind kind = element.kind;
-      if (identical(kind, ElementKind.VARIABLE) ||
-          identical(kind, ElementKind.PARAMETER)) {
+      if (kind == ElementKind.VARIABLE ||
+          kind == ElementKind.PARAMETER) {
         // The name is not guaranteed to be unique.
-        return guess;
+        return safeName(guess);
       }
-      if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) ||
-          identical(kind, ElementKind.FUNCTION) ||
-          identical(kind, ElementKind.CLASS) ||
-          identical(kind, ElementKind.FIELD) ||
-          identical(kind, ElementKind.GETTER) ||
-          identical(kind, ElementKind.SETTER) ||
-          identical(kind, ElementKind.TYPEDEF) ||
-          identical(kind, ElementKind.LIBRARY) ||
-          identical(kind, ElementKind.MALFORMED_TYPE)) {
-        String result = getFreshGlobalName(guess);
+      if (kind == ElementKind.GENERATIVE_CONSTRUCTOR ||
+          kind == ElementKind.FUNCTION ||
+          kind == ElementKind.CLASS ||
+          kind == ElementKind.FIELD ||
+          kind == ElementKind.GETTER ||
+          kind == ElementKind.SETTER ||
+          kind == ElementKind.TYPEDEF ||
+          kind == ElementKind.LIBRARY ||
+          kind == ElementKind.MALFORMED_TYPE) {
+        bool fixedName = false;
+        if (kind == ElementKind.CLASS) {
+          ClassElement classElement = element;
+          fixedName = classElement.isNative();
+        }
+        if (Elements.isInstanceField(element)) {
+          fixedName = element.hasFixedBackendName();
+        }
+        String result =
+            fixedName ? guess : getFreshName(guess, usedGlobalNames);
         globals[element] = result;
         return result;
       }
@@ -331,13 +452,12 @@
   }
 
   String getLazyInitializerName(Element element) {
-    // TODO(floitsch): mangle while not conflicting with other statics.
     assert(Elements.isStaticOrTopLevelField(element));
-    return "get\$${getName(element)}";
+    return getMappedGlobalName("get\$${getName(element)}");
   }
 
   String isolatePropertiesAccess(Element element) {
-    return "$ISOLATE.$ISOLATE_PROPERTIES.${getName(element)}";
+    return "$isolateName.$isolatePropertiesName.${getName(element)}";
   }
 
   String isolateAccess(Element element) {
@@ -345,7 +465,8 @@
   }
 
   String isolateBailoutAccess(Element element) {
-    return '${isolateAccess(element)}\$bailout';
+    String newName = getMappedGlobalName('${getName(element)}\$bailout');
+    return '$CURRENT_ISOLATE.$newName';
   }
 
   String isolateLazyInitializerAccess(Element element) {
@@ -353,6 +474,7 @@
   }
 
   String operatorIs(Element element) {
+    // TODO(erikcorry): Reduce from is$x to ix when we are minifying.
     return 'is\$${getName(element)}';
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index 6b8771d..1104974 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -48,6 +48,10 @@
   Compiler get compiler => emitter.compiler;
   JavaScriptBackend get backend => compiler.backend;
 
+  String get _ => emitter._;
+  String get n => emitter.n;
+  String get N => emitter.N;
+
   String get dynamicName {
     Element element = compiler.findHelper(
         const SourceString('dynamicFunction'));
@@ -111,12 +115,12 @@
     String nativeCode = quotedNative.substring(2, quotedNative.length - 1);
     String className = backend.namer.getName(classElement);
     nativeBuffer.add(className);
-    nativeBuffer.add(' = ');
+    nativeBuffer.add('$_=$_');
     nativeBuffer.add(nativeCode);
-    nativeBuffer.add(';\n');
+    nativeBuffer.add('$N');
 
     void defineInstanceMember(String name, CodeBuffer value) {
-      nativeBuffer.add("$className.$name = $value;\n");
+      nativeBuffer.add("$className.$name$_=$_$value$N");
     }
 
     classElement.implementation.forEachMember((_, Element member) {
@@ -160,7 +164,8 @@
     CodeBuffer getterSetterBuffer = new CodeBuffer();
     CodeBuffer methodBuffer = new CodeBuffer();
 
-    emitter.emitClassFields(classElement, fieldBuffer, false, isNative: true);
+    emitter.emitClassFields(classElement, fieldBuffer, false,
+                            classIsNative: true);
     emitter.emitClassGettersSetters(classElement, getterSetterBuffer, false);
     emitter.emitInstanceMembers(classElement, methodBuffer, false);
 
@@ -171,7 +176,7 @@
     }
 
     String nativeTag = toNativeTag(classElement);
-    nativeBuffer.add("$defineNativeClassName('$nativeTag', ");
+    nativeBuffer.add("$defineNativeClassName('$nativeTag',$_");
     nativeBuffer.add('{');
     bool firstInMap = true;
     if (!fieldBuffer.isEmpty) {
@@ -181,14 +186,14 @@
     if (!getterSetterBuffer.isEmpty) {
       if (!firstInMap) nativeBuffer.add(",");
       firstInMap = false;
-      nativeBuffer.add("\n ");
+      nativeBuffer.add("\n$_");
       nativeBuffer.add(getterSetterBuffer);
     }
     if (!methodBuffer.isEmpty) {
       if (!firstInMap) nativeBuffer.add(",");
       nativeBuffer.add(methodBuffer);
     }
-    nativeBuffer.add('\n});\n\n');
+    nativeBuffer.add('$n})$N$n');
 
     classesWithDynamicDispatch.add(classElement);
   }
@@ -266,7 +271,7 @@
     } else {
       // When calling a JS method, we call it with the native name, and only the
       // arguments up until the last one provided.
-      target = member.nativeName();
+      target = member.fixedBackendName();
       arguments = argumentsBuffer.getRange(
           0, indexOfLastOptionalArgumentInParameters + 1);
     }
@@ -337,7 +342,9 @@
   void emitDynamicDispatchMetadata() {
     if (classesWithDynamicDispatch.isEmpty) return;
     int length = classesWithDynamicDispatch.length;
-    nativeBuffer.add('// $length dynamic classes.\n');
+    if (!compiler.enableMinification) {
+      nativeBuffer.add('// $length dynamic classes.\n');
+    }
 
     // Build a pre-order traversal over all the classes and their subclasses.
     Set<ClassElement> seen = new Set<ClassElement>();
@@ -354,10 +361,14 @@
         (cls) => !getDirectSubclasses(cls).isEmpty &&
                   classesWithDynamicDispatch.contains(cls));
 
-    nativeBuffer.add('// ${classes.length} classes\n');
+    if (!compiler.enableMinification) {
+      nativeBuffer.add('// ${classes.length} classes\n');
+    }
     Collection<ClassElement> classesThatHaveSubclasses = classes.filter(
         (ClassElement t) => !getDirectSubclasses(t).isEmpty);
-    nativeBuffer.add('// ${classesThatHaveSubclasses.length} !leaf\n');
+    if (!compiler.enableMinification) {
+      nativeBuffer.add('// ${classesThatHaveSubclasses.length} !leaf\n');
+    }
 
     // Generate code that builds the map from cls tags used in dynamic dispatch
     // to the set of cls tags of classes that extend (TODO: or implement) those
@@ -399,13 +410,13 @@
           } else {
             // [subclass] is one of the preorderDispatchClasses, so CSE this
             // reference with the previous reference.
-            if (existing is js.VariableUse &&
-                varDefns.containsKey(existing.name)) {
+            js.VariableUse use = existing.asVariableUse();
+            if (use != null && varDefns.containsKey(use.name)) {
               // We end up here if the subclasses have a DAG structure.  We
               // don't have DAGs yet, but if the dispatch is used for mixins
               // that will be a possibility.
               // Re-use the previously created temporary variable.
-              expressions.add(new js.VariableUse(existing.name));
+              expressions.add(new js.VariableUse(use.name));
             } else {
               String varName = 'v${varNames.length}_${tag.name.slowToString()}';
               varNames.add(varName);
@@ -475,6 +486,7 @@
                   [table])));
 
       //  (function(){statements})();
+      if (emitter.compiler.enableMinification) nativeBuffer.add(';');
       nativeBuffer.add(
           js.prettyPrint(
               new js.ExpressionStatement(
@@ -514,7 +526,7 @@
       if (!requiresNativeIsCheck(element)) continue;
       if (element.isObject(compiler)) continue;
       String name = backend.namer.operatorIs(element);
-      objectProperties[name] = 'function() { return false; }';
+      objectProperties[name] = 'function()$_{${_}return false;$_}';
     }
   }
 
@@ -522,7 +534,7 @@
     if (nativeClasses.isEmpty) return;
     emitDynamicDispatchMetadata();
     targetBuffer.add('$defineNativeClassName = '
-                     '$defineNativeClassFunction;\n\n');
+                     '$defineNativeClassFunction$N$n');
 
     // Because of native classes, we have to generate some is checks
     // by calling a method, instead of accessing a property. So we
@@ -540,8 +552,8 @@
         'function() { return $toStringHelperName(this); }';
 
     // Same as above, but for hashCode.
-    String hashCodeName = backend.namer.publicGetterName(
-        const SourceString('hashCode'));
+    String hashCodeName =
+        backend.namer.publicGetterName(const SourceString('hashCode'));
     objectProperties[hashCodeName] =
         'function() { return $hashCodeHelperName(this); }';
 
@@ -556,6 +568,7 @@
     // If we have any properties to add to Object.prototype, we run
     // through them and add them using defineProperty.
     if (!objectProperties.isEmpty) {
+      if (emitter.compiler.enableMinification) targetBuffer.add(";");
       targetBuffer.add("(function(table) {\n"
                        "  for (var key in table) {\n"
                        "    $defPropName(Object.prototype, key, table[key]);\n"
@@ -564,10 +577,10 @@
       bool first = true;
       objectProperties.forEach((String name, String function) {
         if (!first) targetBuffer.add(",\n");
-        targetBuffer.add(" $name: $function");
+        targetBuffer.add("$_$name:$_$function");
         first = false;
       });
-      targetBuffer.add("\n});\n\n");
+      targetBuffer.add("\n})$N$n");
     }
     targetBuffer.add(nativeBuffer);
     targetBuffer.add('\n');
diff --git a/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart b/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart
index fcbd58a..53d276e 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+part of _js_helper;
+
 // This class has no constructor. This is on purpose since the instantiation
 // is shortcut by the compiler.
 class ConstantMap<V> implements Map<String, V> {
diff --git a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
index 38b90d1..b375a97 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
@@ -211,3 +211,8 @@
                           multiLine: multiLine,
                           ignoreCase: ignoreCase);
 }
+
+// Patch for 'identical' function.
+patch bool identical(Object a, Object b) {
+  throw new Error('Should not reach the body of identical');
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
index 9b677d6..dd17e1b 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
@@ -162,12 +162,14 @@
 
 patch class ServerSocket {
   patch factory ServerSocket(String bindAddress, int port, int backlog) {
-    return new _ServerSocket(bindAddress, port, backlog);
+    throw new UnsupportedError("ServerSocket constructor");
   }
 }
 
 patch class Socket {
-  patch factory Socket(String host, int port) => new _Socket(host, port);
+  patch factory Socket(String host, int port) {
+    throw new UnsupportedError("Socket constructor");
+  }
 }
 
 patch class SecureSocket {
@@ -185,11 +187,11 @@
 }
 
 patch class _StdIOUtils {
-  patch static _getStdioHandle(Socket socket, int num) {
-    throw new UnsupportedError("StdIOUtils._getStdioHandle");
+  patch static InputStream _getStdioInputStream() {
+    throw new UnsupportedError("StdIOUtils._getStdioInputStream");
   }
-  patch static _getStdioHandleType(int num) {
-    throw new UnsupportedError("StdIOUtils._getStdioHandleType");
+  patch static OutputStream _getStdioOutputStream(int fd) {
+    throw new UnsupportedError("StdIOUtils._getStdioOutputStream");
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
new file mode 100644
index 0000000..f2b8daa
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
@@ -0,0 +1,1283 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library _isolate_helper;
+
+import 'dart:isolate';
+import 'dart:uri';
+
+/**
+ * Called by the compiler to support switching
+ * between isolates when we get a callback from the DOM.
+ */
+void _callInIsolate(_IsolateContext isolate, Function function) {
+  isolate.eval(function);
+  _globalState.topEventLoop.run();
+}
+
+/**
+ * Called by the compiler to fetch the current isolate context.
+ */
+_IsolateContext _currentIsolate() => _globalState.currentContext;
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/compiler_hooks.dart
+ ********************************************************/
+
+/**
+ * Wrapper that takes the dart entry point and runs it within an isolate. The
+ * dart2js compiler will inject a call of the form
+ * [: startRootIsolate(main); :] when it determines that this wrapping
+ * is needed. For single-isolate applications (e.g. hello world), this
+ * call is not emitted.
+ */
+void startRootIsolate(entry) {
+  _globalState = new _Manager();
+
+  // Don't start the main loop again, if we are in a worker.
+  if (_globalState.isWorker) return;
+  final rootContext = new _IsolateContext();
+  _globalState.rootContext = rootContext;
+  _fillStatics(rootContext);
+
+  // BUG(5151491): Setting currentContext should not be necessary, but
+  // because closures passed to the DOM as event handlers do not bind their
+  // isolate automatically we try to give them a reasonable context to live in
+  // by having a "default" isolate (the first one created).
+  _globalState.currentContext = rootContext;
+
+  rootContext.eval(entry);
+  _globalState.topEventLoop.run();
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/isolateimpl.dart
+ ********************************************************/
+
+/**
+ * Concepts used here:
+ *
+ * "manager" - A manager contains one or more isolates, schedules their
+ * execution, and performs other plumbing on their behalf.  The isolate
+ * present at the creation of the manager is designated as its "root isolate".
+ * A manager may, for example, be implemented on a web Worker.
+ *
+ * [_Manager] - State present within a manager (exactly once, as a global).
+ *
+ * [_ManagerStub] - A handle held within one manager that allows interaction
+ * with another manager.  A target manager may be addressed by zero or more
+ * [_ManagerStub]s.
+ *
+ */
+
+/**
+ * A native object that is shared across isolates. This object is visible to all
+ * isolates running under the same manager (either UI or background web worker).
+ *
+ * This is code that is intended to 'escape' the isolate boundaries in order to
+ * implement the semantics of isolates in JavaScript. Without this we would have
+ * been forced to implement more code (including the top-level event loop) in
+ * JavaScript itself.
+ */
+// TODO(eub, sigmund): move the "manager" to be entirely in JS.
+// Running any Dart code outside the context of an isolate gives it
+// the change to break the isolate abstraction.
+_Manager get _globalState => JS("_Manager", r"$globalState");
+set _globalState(_Manager val) {
+  JS("void", r"$globalState = #", val);
+}
+
+void _fillStatics(context) {
+  JS("void", r"$globals = #.isolateStatics", context);
+  JS("void", r"$static_init()");
+}
+
+ReceivePort lazyPort;
+
+/** State associated with the current manager. See [globalState]. */
+// TODO(sigmund): split in multiple classes: global, thread, main-worker states?
+class _Manager {
+
+  /** Next available isolate id within this [_Manager]. */
+  int nextIsolateId = 0;
+
+  /** id assigned to this [_Manager]. */
+  int currentManagerId = 0;
+
+  /**
+   * Next available manager id. Only used by the main manager to assign a unique
+   * id to each manager created by it.
+   */
+  int nextManagerId = 1;
+
+  /** Context for the currently running [Isolate]. */
+  _IsolateContext currentContext = null;
+
+  /** Context for the root [Isolate] that first run in this [_Manager]. */
+  _IsolateContext rootContext = null;
+
+  /** The top-level event loop. */
+  _EventLoop topEventLoop;
+
+  /** Whether this program is running from the command line. */
+  bool fromCommandLine;
+
+  /** Whether this [_Manager] is running as a web worker. */
+  bool isWorker;
+
+  /** Whether we support spawning web workers. */
+  bool supportsWorkers;
+
+  /**
+   * Whether to use web workers when implementing isolates. Set to false for
+   * debugging/testing.
+   */
+  bool get useWorkers => supportsWorkers;
+
+  /**
+   * Whether to use the web-worker JSON-based message serialization protocol. By
+   * default this is only used with web workers. For debugging, you can force
+   * using this protocol by changing this field value to [true].
+   */
+  bool get needSerialization => useWorkers;
+
+  /**
+   * Registry of isolates. Isolates must be registered if, and only if, receive
+   * ports are alive.  Normally no open receive-ports means that the isolate is
+   * dead, but DOM callbacks could resurrect it.
+   */
+  Map<int, _IsolateContext> isolates;
+
+  /** Reference to the main [_Manager].  Null in the main [_Manager] itself. */
+  _ManagerStub mainManager;
+
+  /** Registry of active [_ManagerStub]s.  Only used in the main [_Manager]. */
+  Map<int, _ManagerStub> managers;
+
+  _Manager() {
+    _nativeDetectEnvironment();
+    topEventLoop = new _EventLoop();
+    isolates = new Map<int, _IsolateContext>();
+    managers = new Map<int, _ManagerStub>();
+    if (isWorker) {  // "if we are not the main manager ourself" is the intent.
+      mainManager = new _MainManagerStub();
+      _nativeInitWorkerMessageHandler();
+    }
+  }
+
+  void _nativeDetectEnvironment() {
+    isWorker = JS("bool", r"$isWorker");
+    supportsWorkers = JS("bool", r"$supportsWorkers");
+    fromCommandLine = JS("bool", r"typeof(window) == 'undefined'");
+  }
+
+  void _nativeInitWorkerMessageHandler() {
+    JS("void", r"""
+$globalThis.onmessage = function (e) {
+  IsolateNatives._processWorkerMessage(this.mainManager, e);
+}""");
+  }
+  /*: TODO: check that _processWorkerMessage is not discarded while treeshaking.
+  """ {
+    IsolateNatives._processWorkerMessage(null, null);
+  }
+  */
+
+
+  /** Close the worker running this code if all isolates are done. */
+  void maybeCloseWorker() {
+    if (isolates.isEmpty) {
+      mainManager.postMessage(_serializeMessage({'command': 'close'}));
+    }
+  }
+}
+
+/** Context information tracked for each isolate. */
+class _IsolateContext {
+  /** Current isolate id. */
+  int id;
+
+  /** Registry of receive ports currently active on this isolate. */
+  Map<int, ReceivePort> ports;
+
+  /** Holds isolate globals (statics and top-level properties). */
+  var isolateStatics; // native object containing all globals of an isolate.
+
+  _IsolateContext() {
+    id = _globalState.nextIsolateId++;
+    ports = new Map<int, ReceivePort>();
+    initGlobals();
+  }
+
+  // these are filled lazily the first time the isolate starts running.
+  void initGlobals() { JS("void", r'$initGlobals(#)', this); }
+
+  /**
+   * Run [code] in the context of the isolate represented by [this]. Note this
+   * is called from JavaScript (see $wrap_call in corejs.dart).
+   */
+  dynamic eval(Function code) {
+    var old = _globalState.currentContext;
+    _globalState.currentContext = this;
+    this._setGlobals();
+    var result = null;
+    try {
+      result = code();
+    } finally {
+      _globalState.currentContext = old;
+      if (old != null) old._setGlobals();
+    }
+    return result;
+  }
+
+  void _setGlobals() { JS("void", r'$setGlobals(#)', this); }
+
+  /** Lookup a port registered for this isolate. */
+  ReceivePort lookup(int portId) => ports[portId];
+
+  /** Register a port on this isolate. */
+  void register(int portId, ReceivePort port)  {
+    if (ports.containsKey(portId)) {
+      throw new Exception("Registry: ports must be registered only once.");
+    }
+    ports[portId] = port;
+    _globalState.isolates[id] = this; // indicate this isolate is active
+  }
+
+  /** Unregister a port on this isolate. */
+  void unregister(int portId) {
+    ports.remove(portId);
+    if (ports.isEmpty) {
+      _globalState.isolates.remove(id); // indicate this isolate is not active
+    }
+  }
+}
+
+/** Represent the event loop on a javascript thread (DOM or worker). */
+class _EventLoop {
+  Queue<_IsolateEvent> events;
+
+  _EventLoop() : events = new Queue<_IsolateEvent>();
+
+  void enqueue(isolate, fn, msg) {
+    events.addLast(new _IsolateEvent(isolate, fn, msg));
+  }
+
+  _IsolateEvent dequeue() {
+    if (events.isEmpty) return null;
+    return events.removeFirst();
+  }
+
+  /** Process a single event, if any. */
+  bool runIteration() {
+    final event = dequeue();
+    if (event == null) {
+      if (_globalState.isWorker) {
+        _globalState.maybeCloseWorker();
+      } else if (_globalState.rootContext != null &&
+                 _globalState.isolates.containsKey(
+                     _globalState.rootContext.id) &&
+                 _globalState.fromCommandLine &&
+                 _globalState.rootContext.ports.isEmpty) {
+        // We want to reach here only on the main [_Manager] and only
+        // on the command-line.  In the browser the isolate might
+        // still be alive due to DOM callbacks, but the presumption is
+        // that on the command-line, no future events can be injected
+        // into the event queue once it's empty.  Node has setTimeout
+        // so this presumption is incorrect there.  We think(?) that
+        // in d8 this assumption is valid.
+        throw new Exception("Program exited with open ReceivePorts.");
+      }
+      return false;
+    }
+    event.process();
+    return true;
+  }
+
+  /**
+   * Runs multiple iterations of the run-loop. If possible, each iteration is
+   * run asynchronously.
+   */
+  void _runHelper() {
+    if (hasWindow()) {
+      // Run each iteration from the browser's top event loop.
+      void next() {
+        if (!runIteration()) return;
+        _window.setTimeout(next, 0);
+      }
+      next();
+    } else {
+      // Run synchronously until no more iterations are available.
+      while (runIteration()) {}
+    }
+  }
+
+  /**
+   * Call [_runHelper] but ensure that worker exceptions are propragated. Note
+   * this is called from JavaScript (see $wrap_call in corejs.dart).
+   */
+  void run() {
+    if (!_globalState.isWorker) {
+      _runHelper();
+    } else {
+      try {
+        _runHelper();
+      } catch (e, trace) {
+        _globalState.mainManager.postMessage(_serializeMessage(
+            {'command': 'error', 'msg': '$e\n$trace' }));
+      }
+    }
+  }
+}
+
+/** An event in the top-level event queue. */
+class _IsolateEvent {
+  _IsolateContext isolate;
+  Function fn;
+  String message;
+
+  _IsolateEvent(this.isolate, this.fn, this.message);
+
+  void process() {
+    isolate.eval(fn);
+  }
+}
+
+/** An interface for a stub used to interact with a manager. */
+abstract class _ManagerStub {
+  get id;
+  void set id(int i);
+  void set onmessage(Function f);
+  void postMessage(msg);
+  void terminate();
+}
+
+/** A stub for interacting with the main manager. */
+class _MainManagerStub implements _ManagerStub {
+  get id => 0;
+  void set id(int i) { throw new UnimplementedError(); }
+  void set onmessage(f) {
+    throw new Exception("onmessage should not be set on MainManagerStub");
+  }
+  void postMessage(msg) { JS("void", r"$globalThis.postMessage(#)", msg); }
+  void terminate() {}  // Nothing useful to do here.
+}
+
+/**
+ * A stub for interacting with a manager built on a web worker. This
+ * definition uses a 'hidden' type (* prefix on the native name) to
+ * enforce that the type is defined dynamically only when web workers
+ * are actually available.
+ */
+// @Native("*Worker");
+class _WorkerStub implements _ManagerStub {
+  get id => JS("var", "#.id", this);
+  void set id(i) { JS("void", "#.id = #", this, i); }
+  void set onmessage(f) { JS("void", "#.onmessage = #", this, f); }
+  void postMessage(msg) => JS("void", "#.postMessage(#)", this, msg);
+  // terminate() is implemented by Worker.
+  void terminate();
+}
+
+const String _SPAWNED_SIGNAL = "spawned";
+
+class IsolateNatives {
+
+  /**
+   * The src url for the script tag that loaded this code. Used to create
+   * JavaScript workers.
+   */
+  static String get _thisScript => JS("String", r"$thisScriptUrl");
+
+  /** Starts a new worker with the given URL. */
+  static _WorkerStub _newWorker(url) => JS("_WorkerStub", r"new Worker(#)", url);
+
+  /**
+   * Assume that [e] is a browser message event and extract its message data.
+   * We don't import the dom explicitly so, when workers are disabled, this
+   * library can also run on top of nodejs.
+   */
+  //static _getEventData(e) => JS("Object", "#.data", e);
+  static _getEventData(e) => JS("", "#.data", e);
+
+  /**
+   * Process messages on a worker, either to control the worker instance or to
+   * pass messages along to the isolate running in the worker.
+   */
+  static void _processWorkerMessage(sender, e) {
+    var msg = _deserializeMessage(_getEventData(e));
+    switch (msg['command']) {
+      case 'start':
+        _globalState.currentManagerId = msg['id'];
+        Function entryPoint = _getJSFunctionFromName(msg['functionName']);
+        var replyTo = _deserializeMessage(msg['replyTo']);
+        _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
+          _startIsolate(entryPoint, replyTo);
+        }, 'worker-start');
+        _globalState.topEventLoop.run();
+        break;
+      case 'spawn-worker':
+        _spawnWorker(msg['functionName'], msg['uri'], msg['replyPort']);
+        break;
+      case 'message':
+        msg['port'].send(msg['msg'], msg['replyTo']);
+        _globalState.topEventLoop.run();
+        break;
+      case 'close':
+        _log("Closing Worker");
+        _globalState.managers.remove(sender.id);
+        sender.terminate();
+        _globalState.topEventLoop.run();
+        break;
+      case 'log':
+        _log(msg['msg']);
+        break;
+      case 'print':
+        if (_globalState.isWorker) {
+          _globalState.mainManager.postMessage(
+              _serializeMessage({'command': 'print', 'msg': msg}));
+        } else {
+          print(msg['msg']);
+        }
+        break;
+      case 'error':
+        throw msg['msg'];
+    }
+  }
+
+  /** Log a message, forwarding to the main [_Manager] if appropriate. */
+  static _log(msg) {
+    if (_globalState.isWorker) {
+      _globalState.mainManager.postMessage(
+          _serializeMessage({'command': 'log', 'msg': msg }));
+    } else {
+      try {
+        _consoleLog(msg);
+      } catch (e, trace) {
+        throw new Exception(trace);
+      }
+    }
+  }
+
+  static void _consoleLog(msg) {
+    JS("void", r"$globalThis.console.log(#)", msg);
+  }
+
+  /**
+   * Extract the constructor of runnable, so it can be allocated in another
+   * isolate.
+   */
+  static dynamic _getJSConstructor(Isolate runnable) {
+    return JS("Object", "#.constructor", runnable);
+  }
+
+  /** Extract the constructor name of a runnable */
+  // TODO(sigmund): find a browser-generic way to support this.
+  // TODO(floitsch): is this function still used? If yes, should we use
+  // Primitives.objectTypeName instead?
+  static dynamic _getJSConstructorName(Isolate runnable) {
+    return JS("Object", "#.constructor.name", runnable);
+  }
+
+  /** Find a constructor given its name. */
+  static dynamic _getJSConstructorFromName(String factoryName) {
+    return JS("Object", r"$globalThis[#]", factoryName);
+  }
+
+  static dynamic _getJSFunctionFromName(String functionName) {
+    return JS("Object", r"$globalThis[#]", functionName);
+  }
+
+  /**
+   * Get a string name for the function, if possible.  The result for
+   * anonymous functions is browser-dependent -- it may be "" or "anonymous"
+   * but you should probably not count on this.
+   */
+  static String _getJSFunctionName(Function f) {
+    return JS("Object", r"(#.$name || #)", f, null);
+  }
+
+  /** Create a new JavaScript object instance given its constructor. */
+  static dynamic _allocate(var ctor) {
+    return JS("Object", "new #()", ctor);
+  }
+
+  static SendPort spawnFunction(void topLevelFunction()) {
+    final name = _getJSFunctionName(topLevelFunction);
+    if (name == null) {
+      throw new UnsupportedError(
+          "only top-level functions can be spawned.");
+    }
+    return spawn(name, null, false);
+  }
+
+  // TODO(sigmund): clean up above, after we make the new API the default:
+
+  static SendPort spawn(String functionName, String uri, bool isLight) {
+    Completer<SendPort> completer = new Completer<SendPort>();
+    ReceivePort port = new ReceivePort();
+    port.receive((msg, SendPort replyPort) {
+      port.close();
+      assert(msg == _SPAWNED_SIGNAL);
+      completer.complete(replyPort);
+    });
+
+    SendPort signalReply = port.toSendPort();
+
+    if (_globalState.useWorkers && !isLight) {
+      _startWorker(functionName, uri, signalReply);
+    } else {
+      _startNonWorker(functionName, uri, signalReply);
+    }
+    return new _BufferingSendPort(
+        _globalState.currentContext.id, completer.future);
+  }
+
+  static SendPort _startWorker(
+      String functionName, String uri, SendPort replyPort) {
+    if (_globalState.isWorker) {
+      _globalState.mainManager.postMessage(_serializeMessage({
+          'command': 'spawn-worker',
+          'functionName': functionName,
+          'uri': uri,
+          'replyPort': replyPort}));
+    } else {
+      _spawnWorker(functionName, uri, replyPort);
+    }
+  }
+
+  static SendPort _startNonWorker(
+      String functionName, String uri, SendPort replyPort) {
+    // TODO(eub): support IE9 using an iframe -- Dart issue 1702.
+    if (uri != null) throw new UnsupportedError(
+            "Currently spawnUri is not supported without web workers.");
+    _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
+      final func = _getJSFunctionFromName(functionName);
+      _startIsolate(func, replyPort);
+    }, 'nonworker start');
+  }
+
+  static void _startIsolate(Function topLevel, SendPort replyTo) {
+    _fillStatics(_globalState.currentContext);
+    lazyPort = new ReceivePort();
+    replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
+
+    topLevel();
+  }
+
+  /**
+   * Spawns an isolate in a worker. [factoryName] is the Javascript constructor
+   * name for the isolate entry point class.
+   */
+  static void _spawnWorker(functionName, uri, replyPort) {
+    if (functionName == null) functionName = 'main';
+    if (uri == null) uri = _thisScript;
+    if (!(new Uri.fromString(uri).isAbsolute())) {
+      // The constructor of dom workers requires an absolute URL. If we use a
+      // relative path we will get a DOM exception.
+      String prefix = _thisScript.substring(0, _thisScript.lastIndexOf('/'));
+      uri = "$prefix/$uri";
+    }
+    final worker = _newWorker(uri);
+    worker.onmessage = (e) { _processWorkerMessage(worker, e); };
+    var workerId = _globalState.nextManagerId++;
+    // We also store the id on the worker itself so that we can unregister it.
+    worker.id = workerId;
+    _globalState.managers[workerId] = worker;
+    worker.postMessage(_serializeMessage({
+      'command': 'start',
+      'id': workerId,
+      // Note: we serialize replyPort twice because the child worker needs to
+      // first deserialize the worker id, before it can correctly deserialize
+      // the port (port deserialization is sensitive to what is the current
+      // workerId).
+      'replyTo': _serializeMessage(replyPort),
+      'functionName': functionName }));
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/ports.dart
+ ********************************************************/
+
+/** Common functionality to all send ports. */
+class _BaseSendPort implements SendPort {
+  /** Id for the destination isolate. */
+  final int _isolateId;
+
+  const _BaseSendPort(this._isolateId);
+
+  void _checkReplyTo(SendPort replyTo) {
+    if (replyTo != null
+        && replyTo is! _NativeJsSendPort
+        && replyTo is! _WorkerSendPort
+        && replyTo is! _BufferingSendPort) {
+      throw new Exception("SendPort.send: Illegal replyTo port type");
+    }
+  }
+
+  Future call(var message) {
+    final completer = new Completer();
+    final port = new ReceivePortImpl();
+    send(message, port.toSendPort());
+    port.receive((value, ignoreReplyTo) {
+      port.close();
+      if (value is Exception) {
+        completer.completeException(value);
+      } else {
+        completer.complete(value);
+      }
+    });
+    return completer.future;
+  }
+
+  void send(var message, [SendPort replyTo]);
+  bool operator ==(var other);
+  int get hashCode;
+}
+
+/** A send port that delivers messages in-memory via native JavaScript calls. */
+class _NativeJsSendPort extends _BaseSendPort implements SendPort {
+  final ReceivePortImpl _receivePort;
+
+  const _NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId);
+
+  void send(var message, [SendPort replyTo = null]) {
+    _waitForPendingPorts([message, replyTo], () {
+      _checkReplyTo(replyTo);
+      // Check that the isolate still runs and the port is still open
+      final isolate = _globalState.isolates[_isolateId];
+      if (isolate == null) return;
+      if (_receivePort._callback == null) return;
+
+      // We force serialization/deserialization as a simple way to ensure
+      // isolate communication restrictions are respected between isolates that
+      // live in the same worker. [_NativeJsSendPort] delivers both messages
+      // from the same worker and messages from other workers. In particular,
+      // messages sent from a worker via a [_WorkerSendPort] are received at
+      // [_processWorkerMessage] and forwarded to a native port. In such cases,
+      // here we'll see [_globalState.currentContext == null].
+      final shouldSerialize = _globalState.currentContext != null
+          && _globalState.currentContext.id != _isolateId;
+      var msg = message;
+      var reply = replyTo;
+      if (shouldSerialize) {
+        msg = _serializeMessage(msg);
+        reply = _serializeMessage(reply);
+      }
+      _globalState.topEventLoop.enqueue(isolate, () {
+        if (_receivePort._callback != null) {
+          if (shouldSerialize) {
+            msg = _deserializeMessage(msg);
+            reply = _deserializeMessage(reply);
+          }
+          _receivePort._callback(msg, reply);
+        }
+      }, 'receive $message');
+    });
+  }
+
+  bool operator ==(var other) => (other is _NativeJsSendPort) &&
+      (_receivePort == other._receivePort);
+
+  int get hashCode => _receivePort._id;
+}
+
+/** A send port that delivers messages via worker.postMessage. */
+// TODO(eub): abstract this for iframes.
+class _WorkerSendPort extends _BaseSendPort implements SendPort {
+  final int _workerId;
+  final int _receivePortId;
+
+  const _WorkerSendPort(this._workerId, int isolateId, this._receivePortId)
+      : super(isolateId);
+
+  void send(var message, [SendPort replyTo = null]) {
+    _waitForPendingPorts([message, replyTo], () {
+      _checkReplyTo(replyTo);
+      final workerMessage = _serializeMessage({
+          'command': 'message',
+          'port': this,
+          'msg': message,
+          'replyTo': replyTo});
+
+      if (_globalState.isWorker) {
+        // communication from one worker to another go through the main worker:
+        _globalState.mainManager.postMessage(workerMessage);
+      } else {
+        _globalState.managers[_workerId].postMessage(workerMessage);
+      }
+    });
+  }
+
+  bool operator ==(var other) {
+    return (other is _WorkerSendPort) &&
+        (_workerId == other._workerId) &&
+        (_isolateId == other._isolateId) &&
+        (_receivePortId == other._receivePortId);
+  }
+
+  int get hashCode {
+    // TODO(sigmund): use a standard hash when we get one available in corelib.
+    return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId;
+  }
+}
+
+/** A port that buffers messages until an underlying port gets resolved. */
+class _BufferingSendPort extends _BaseSendPort implements SendPort {
+  /** Internal counter to assign unique ids to each port. */
+  static int _idCount = 0;
+
+  /** For implementing equals and hashcode. */
+  final int _id;
+
+  /** Underlying port, when resolved. */
+  SendPort _port;
+
+  /**
+   * Future of the underlying port, so that we can detect when this port can be
+   * sent on messages.
+   */
+  Future<SendPort> _futurePort;
+
+  /** Pending messages (and reply ports). */
+  List pending;
+
+  _BufferingSendPort(isolateId, this._futurePort)
+      : super(isolateId), _id = _idCount, pending = [] {
+    _idCount++;
+    _futurePort.then((p) {
+      _port = p;
+      for (final item in pending) {
+        p.send(item['message'], item['replyTo']);
+      }
+      pending = null;
+    });
+  }
+
+  _BufferingSendPort.fromPort(isolateId, this._port)
+      : super(isolateId), _id = _idCount {
+    _idCount++;
+  }
+
+  void send(var message, [SendPort replyTo]) {
+    if (_port != null) {
+      _port.send(message, replyTo);
+    } else {
+      pending.add({'message': message, 'replyTo': replyTo});
+    }
+  }
+
+  bool operator ==(var other) =>
+      other is _BufferingSendPort && _id == other._id;
+  int get hashCode => _id;
+}
+
+/** Implementation of a multi-use [ReceivePort] on top of JavaScript. */
+class ReceivePortImpl implements ReceivePort {
+  int _id;
+  Function _callback;
+  static int _nextFreeId = 1;
+
+  ReceivePortImpl()
+      : _id = _nextFreeId++ {
+    _globalState.currentContext.register(_id, this);
+  }
+
+  void receive(void onMessage(var message, SendPort replyTo)) {
+    _callback = onMessage;
+  }
+
+  void close() {
+    _callback = null;
+    _globalState.currentContext.unregister(_id);
+  }
+
+  SendPort toSendPort() {
+    return new _NativeJsSendPort(this, _globalState.currentContext.id);
+  }
+}
+
+/** Wait until all ports in a message are resolved. */
+_waitForPendingPorts(var message, void callback()) {
+  final finder = new _PendingSendPortFinder();
+  finder.traverse(message);
+  Futures.wait(finder.ports).then((_) => callback());
+}
+
+
+/** Visitor that finds all unresolved [SendPort]s in a message. */
+class _PendingSendPortFinder extends _MessageTraverser {
+  List<Future<SendPort>> ports;
+  _PendingSendPortFinder() : super(), ports = [] {
+    _visited = new _JsVisitedMap();
+  }
+
+  visitPrimitive(x) {}
+
+  visitList(List list) {
+    final seen = _visited[list];
+    if (seen != null) return;
+    _visited[list] = true;
+    // TODO(sigmund): replace with the following: (bug #1660)
+    // list.forEach(_dispatch);
+    list.forEach((e) => _dispatch(e));
+  }
+
+  visitMap(Map map) {
+    final seen = _visited[map];
+    if (seen != null) return;
+
+    _visited[map] = true;
+    // TODO(sigmund): replace with the following: (bug #1660)
+    // map.values.forEach(_dispatch);
+    map.values.forEach((e) => _dispatch(e));
+  }
+
+  visitSendPort(SendPort port) {
+    if (port is _BufferingSendPort && port._port == null) {
+      ports.add(port._futurePort);
+    }
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/messages.dart
+ ********************************************************/
+
+// Defines message visitors, serialization, and deserialization.
+
+/** Serialize [message] (or simulate serialization). */
+_serializeMessage(message) {
+  if (_globalState.needSerialization) {
+    return new _JsSerializer().traverse(message);
+  } else {
+    return new _JsCopier().traverse(message);
+  }
+}
+
+/** Deserialize [message] (or simulate deserialization). */
+_deserializeMessage(message) {
+  if (_globalState.needSerialization) {
+    return new _JsDeserializer().deserialize(message);
+  } else {
+    // Nothing more to do.
+    return message;
+  }
+}
+
+class _JsSerializer extends _Serializer {
+
+  _JsSerializer() : super() { _visited = new _JsVisitedMap(); }
+
+  visitSendPort(SendPort x) {
+    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
+    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
+    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
+    throw "Illegal underlying port $x";
+  }
+
+  visitNativeJsSendPort(_NativeJsSendPort port) {
+    return ['sendport', _globalState.currentManagerId,
+        port._isolateId, port._receivePort._id];
+  }
+
+  visitWorkerSendPort(_WorkerSendPort port) {
+    return ['sendport', port._workerId, port._isolateId, port._receivePortId];
+  }
+
+  visitBufferingSendPort(_BufferingSendPort port) {
+    if (port._port != null) {
+      return visitSendPort(port._port);
+    } else {
+      // TODO(floitsch): Use real exception (which one?).
+      throw
+          "internal error: must call _waitForPendingPorts to ensure all"
+          " ports are resolved at this point.";
+    }
+  }
+
+}
+
+
+class _JsCopier extends _Copier {
+
+  _JsCopier() : super() { _visited = new _JsVisitedMap(); }
+
+  visitSendPort(SendPort x) {
+    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
+    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
+    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
+    throw "Illegal underlying port $p";
+  }
+
+  SendPort visitNativeJsSendPort(_NativeJsSendPort port) {
+    return new _NativeJsSendPort(port._receivePort, port._isolateId);
+  }
+
+  SendPort visitWorkerSendPort(_WorkerSendPort port) {
+    return new _WorkerSendPort(
+        port._workerId, port._isolateId, port._receivePortId);
+  }
+
+  SendPort visitBufferingSendPort(_BufferingSendPort port) {
+    if (port._port != null) {
+      return visitSendPort(port._port);
+    } else {
+      // TODO(floitsch): Use real exception (which one?).
+      throw
+          "internal error: must call _waitForPendingPorts to ensure all"
+          " ports are resolved at this point.";
+    }
+  }
+
+}
+
+class _JsDeserializer extends _Deserializer {
+
+  SendPort deserializeSendPort(List x) {
+    int managerId = x[1];
+    int isolateId = x[2];
+    int receivePortId = x[3];
+    // If two isolates are in the same manager, we use NativeJsSendPorts to
+    // deliver messages directly without using postMessage.
+    if (managerId == _globalState.currentManagerId) {
+      var isolate = _globalState.isolates[isolateId];
+      if (isolate == null) return null; // Isolate has been closed.
+      var receivePort = isolate.lookup(receivePortId);
+      return new _NativeJsSendPort(receivePort, isolateId);
+    } else {
+      return new _WorkerSendPort(managerId, isolateId, receivePortId);
+    }
+  }
+
+}
+
+class _JsVisitedMap implements _MessageTraverserVisitedMap {
+  List tagged;
+
+  /** Retrieves any information stored in the native object [object]. */
+  operator[](var object) {
+    return _getAttachedInfo(object);
+  }
+
+  /** Injects some information into the native [object]. */
+  void operator[]=(var object, var info) {
+    tagged.add(object);
+    _setAttachedInfo(object, info);
+  }
+
+  /** Get ready to rumble. */
+  void reset() {
+    assert(tagged == null);
+    tagged = new List();
+  }
+
+  /** Remove all information injected in the native objects. */
+  void cleanup() {
+    for (int i = 0, length = tagged.length; i < length; i++) {
+      _clearAttachedInfo(tagged[i]);
+    }
+    tagged = null;
+  }
+
+  void _clearAttachedInfo(var o) {
+    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, null);
+  }
+
+  void _setAttachedInfo(var o, var info) {
+    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, info);
+  }
+
+  _getAttachedInfo(var o) {
+    return JS("", "#['__MessageTraverser__attached_info__']", o);
+  }
+}
+
+// only visible for testing purposes
+// TODO(sigmund): remove once we can disable privacy for testing (bug #1882)
+class TestingOnly {
+  static copy(x) {
+    return new _JsCopier().traverse(x);
+  }
+
+  // only visible for testing purposes
+  static serialize(x) {
+    _Serializer serializer = new _JsSerializer();
+    _Deserializer deserializer = new _JsDeserializer();
+    return deserializer.deserialize(serializer.traverse(x));
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/serialization.dart
+ ********************************************************/
+
+class _MessageTraverserVisitedMap {
+
+  operator[](var object) => null;
+  void operator[]=(var object, var info) { }
+
+  void reset() { }
+  void cleanup() { }
+
+}
+
+/** Abstract visitor for dart objects that can be sent as isolate messages. */
+class _MessageTraverser {
+
+  _MessageTraverserVisitedMap _visited;
+  _MessageTraverser() : _visited = new _MessageTraverserVisitedMap();
+
+  /** Visitor's entry point. */
+  traverse(var x) {
+    if (isPrimitive(x)) return visitPrimitive(x);
+    _visited.reset();
+    var result;
+    try {
+      result = _dispatch(x);
+    } finally {
+      _visited.cleanup();
+    }
+    return result;
+  }
+
+  _dispatch(var x) {
+    if (isPrimitive(x)) return visitPrimitive(x);
+    if (x is List) return visitList(x);
+    if (x is Map) return visitMap(x);
+    if (x is SendPort) return visitSendPort(x);
+    if (x is SendPortSync) return visitSendPortSync(x);
+
+    // Overridable fallback.
+    return visitObject(x);
+  }
+
+  visitPrimitive(x);
+  visitList(List x);
+  visitMap(Map x);
+  visitSendPort(SendPort x);
+  visitSendPortSync(SendPortSync x);
+
+  visitObject(Object x) {
+    // TODO(floitsch): make this a real exception. (which one)?
+    throw "Message serialization: Illegal value $x passed";
+  }
+
+  static bool isPrimitive(x) {
+    return (x == null) || (x is String) || (x is num) || (x is bool);
+  }
+}
+
+
+/** A visitor that recursively copies a message. */
+class _Copier extends _MessageTraverser {
+
+  visitPrimitive(x) => x;
+
+  List visitList(List list) {
+    List copy = _visited[list];
+    if (copy != null) return copy;
+
+    int len = list.length;
+
+    // TODO(floitsch): we loose the generic type of the List.
+    copy = new List(len);
+    _visited[list] = copy;
+    for (int i = 0; i < len; i++) {
+      copy[i] = _dispatch(list[i]);
+    }
+    return copy;
+  }
+
+  Map visitMap(Map map) {
+    Map copy = _visited[map];
+    if (copy != null) return copy;
+
+    // TODO(floitsch): we loose the generic type of the map.
+    copy = new Map();
+    _visited[map] = copy;
+    map.forEach((key, val) {
+      copy[_dispatch(key)] = _dispatch(val);
+    });
+    return copy;
+  }
+
+}
+
+/** Visitor that serializes a message as a JSON array. */
+class _Serializer extends _MessageTraverser {
+  int _nextFreeRefId = 0;
+
+  visitPrimitive(x) => x;
+
+  visitList(List list) {
+    int copyId = _visited[list];
+    if (copyId != null) return ['ref', copyId];
+
+    int id = _nextFreeRefId++;
+    _visited[list] = id;
+    var jsArray = _serializeList(list);
+    // TODO(floitsch): we are losing the generic type.
+    return ['list', id, jsArray];
+  }
+
+  visitMap(Map map) {
+    int copyId = _visited[map];
+    if (copyId != null) return ['ref', copyId];
+
+    int id = _nextFreeRefId++;
+    _visited[map] = id;
+    var keys = _serializeList(map.keys);
+    var values = _serializeList(map.values);
+    // TODO(floitsch): we are losing the generic type.
+    return ['map', id, keys, values];
+  }
+
+  _serializeList(List list) {
+    int len = list.length;
+    var result = new List(len);
+    for (int i = 0; i < len; i++) {
+      result[i] = _dispatch(list[i]);
+    }
+    return result;
+  }
+}
+
+/** Deserializes arrays created with [_Serializer]. */
+class _Deserializer {
+  Map<int, dynamic> _deserialized;
+
+  _Deserializer();
+
+  static bool isPrimitive(x) {
+    return (x == null) || (x is String) || (x is num) || (x is bool);
+  }
+
+  deserialize(x) {
+    if (isPrimitive(x)) return x;
+    // TODO(floitsch): this should be new HashMap<int, var|Dynamic>()
+    _deserialized = new HashMap();
+    return _deserializeHelper(x);
+  }
+
+  _deserializeHelper(x) {
+    if (isPrimitive(x)) return x;
+    assert(x is List);
+    switch (x[0]) {
+      case 'ref': return _deserializeRef(x);
+      case 'list': return _deserializeList(x);
+      case 'map': return _deserializeMap(x);
+      case 'sendport': return deserializeSendPort(x);
+      default: return deserializeObject(x);
+    }
+  }
+
+  _deserializeRef(List x) {
+    int id = x[1];
+    var result = _deserialized[id];
+    assert(result != null);
+    return result;
+  }
+
+  List _deserializeList(List x) {
+    int id = x[1];
+    // We rely on the fact that Dart-lists are directly mapped to Js-arrays.
+    List dartList = x[2];
+    _deserialized[id] = dartList;
+    int len = dartList.length;
+    for (int i = 0; i < len; i++) {
+      dartList[i] = _deserializeHelper(dartList[i]);
+    }
+    return dartList;
+  }
+
+  Map _deserializeMap(List x) {
+    Map result = new Map();
+    int id = x[1];
+    _deserialized[id] = result;
+    List keys = x[2];
+    List values = x[3];
+    int len = keys.length;
+    assert(len == values.length);
+    for (int i = 0; i < len; i++) {
+      var key = _deserializeHelper(keys[i]);
+      var value = _deserializeHelper(values[i]);
+      result[key] = value;
+    }
+    return result;
+  }
+
+  deserializeSendPort(List x);
+
+  deserializeObject(List x) {
+    // TODO(floitsch): Use real exception (which one?).
+    throw "Unexpected serialized object";
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/timer_provider.dart
+ ********************************************************/
+
+// We don't want to import the DOM library just because of window.setTimeout,
+// so we reconstruct the Window class here. The only conflict that could happen
+// with the other DOMWindow class would be because of subclasses.
+// Currently, none of the two Dart classes have subclasses.
+typedef void _TimeoutHandler();
+
+// @Native("*DOMWindow");
+class _Window {
+  int setTimeout(_TimeoutHandler handler, int timeout) {
+    return JS('int',
+              '#.setTimeout(#, #)',
+              this,
+              convertDartClosureToJS(handler, 0),
+              timeout);
+  }
+
+  int setInterval(_TimeoutHandler handler, int timeout) {
+    return JS('int',
+              '#.setInterval(#, #)',
+              this,
+              convertDartClosureToJS(handler, 0),
+              timeout);
+  }
+
+  void clearTimeout(int handle) {
+    JS('void', '#.clearTimeout(#)', this, handle);
+  }
+
+  void clearInterval(int handle) {
+    JS('void', '#.clearInterval(#)', this, handle);
+  }
+}
+
+_Window get _window =>
+  JS('bool', 'typeof window != "undefined"') ? JS('_Window', 'window') : null;
+
+bool hasWindow() => _window != null;
+
+class TimerImpl implements Timer {
+  final bool _once;
+  int _handle;
+
+  TimerImpl(int milliseconds, void callback(Timer timer))
+      : _once = true {
+    _handle = _window.setTimeout(() => callback(this), milliseconds);
+  }
+
+  TimerImpl.repeating(int milliseconds, void callback(Timer timer))
+      : _once = false {
+    _handle = _window.setInterval(() => callback(this), milliseconds);
+  }
+
+  void cancel() {
+    if (_once) {
+      _window.clearTimeout(_handle);
+    } else {
+      _window.clearInterval(_handle);
+    }
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
index c6356bf..3f43fa3 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
@@ -4,1287 +4,45 @@
 
 // Patch file for the dart:isolate library.
 
-import 'dart:uri';
-
-/**
- * Called by the compiler to support switching
- * between isolates when we get a callback from the DOM.
- */
-void _callInIsolate(_IsolateContext isolate, Function function) {
-  isolate.eval(function);
-  _globalState.topEventLoop.run();
-}
-
-/**
- * Called by the compiler to fetch the current isolate context.
- */
-_IsolateContext _currentIsolate() => _globalState.currentContext;
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/compiler_hooks.dart
- ********************************************************/
-
-/**
- * Wrapper that takes the dart entry point and runs it within an isolate. The
- * dart2js compiler will inject a call of the form
- * [: startRootIsolate(main); :] when it determines that this wrapping
- * is needed. For single-isolate applications (e.g. hello world), this
- * call is not emitted.
- */
-void startRootIsolate(entry) {
-  _globalState = new _Manager();
-
-  // Don't start the main loop again, if we are in a worker.
-  if (_globalState.isWorker) return;
-  final rootContext = new _IsolateContext();
-  _globalState.rootContext = rootContext;
-  _fillStatics(rootContext);
-
-  // BUG(5151491): Setting currentContext should not be necessary, but
-  // because closures passed to the DOM as event handlers do not bind their
-  // isolate automatically we try to give them a reasonable context to live in
-  // by having a "default" isolate (the first one created).
-  _globalState.currentContext = rootContext;
-
-  if (_window != null)  {
-    rootContext.eval(() => _setTimerFactoryClosure( _timerFactory));
-  }
-  rootContext.eval(entry);
-  _globalState.topEventLoop.run();
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/isolateimpl.dart
- ********************************************************/
-
-/**
- * Concepts used here:
- *
- * "manager" - A manager contains one or more isolates, schedules their
- * execution, and performs other plumbing on their behalf.  The isolate
- * present at the creation of the manager is designated as its "root isolate".
- * A manager may, for example, be implemented on a web Worker.
- *
- * [_Manager] - State present within a manager (exactly once, as a global).
- *
- * [_ManagerStub] - A handle held within one manager that allows interaction
- * with another manager.  A target manager may be addressed by zero or more
- * [_ManagerStub]s.
- *
- */
-
-/**
- * A native object that is shared across isolates. This object is visible to all
- * isolates running under the same manager (either UI or background web worker).
- *
- * This is code that is intended to 'escape' the isolate boundaries in order to
- * implement the semantics of isolates in JavaScript. Without this we would have
- * been forced to implement more code (including the top-level event loop) in
- * JavaScript itself.
- */
-// TODO(eub, sigmund): move the "manager" to be entirely in JS.
-// Running any Dart code outside the context of an isolate gives it
-// the change to break the isolate abstraction.
-_Manager get _globalState => JS("_Manager", r"$globalState");
-set _globalState(_Manager val) {
-  JS("void", r"$globalState = #", val);
-}
-
-void _fillStatics(context) {
-  JS("void", r"$globals = #.isolateStatics", context);
-  JS("void", r"$static_init()");
-}
-
-ReceivePort _lazyPort;
 patch ReceivePort get port {
-  if (_lazyPort == null) {
-    _lazyPort = new ReceivePort();
+  if (lazyPort == null) {
+    lazyPort = new ReceivePort();
   }
-  return _lazyPort;
+  return lazyPort;
 }
 
 patch SendPort spawnFunction(void topLevelFunction()) {
-  final name = _IsolateNatives._getJSFunctionName(topLevelFunction);
-  if (name == null) {
-    throw new UnsupportedError(
-        "only top-level functions can be spawned.");
-  }
-  return _IsolateNatives._spawn(name, null, false);
+  return IsolateNatives.spawnFunction(topLevelFunction);
 }
 
 patch SendPort spawnUri(String uri) {
-  return _IsolateNatives._spawn(null, uri, false);
+  return IsolateNatives.spawn(null, uri, false);
 }
 
-/** State associated with the current manager. See [globalState]. */
-// TODO(sigmund): split in multiple classes: global, thread, main-worker states?
-class _Manager {
-
-  /** Next available isolate id within this [_Manager]. */
-  int nextIsolateId = 0;
-
-  /** id assigned to this [_Manager]. */
-  int currentManagerId = 0;
-
-  /**
-   * Next available manager id. Only used by the main manager to assign a unique
-   * id to each manager created by it.
-   */
-  int nextManagerId = 1;
-
-  /** Context for the currently running [Isolate]. */
-  _IsolateContext currentContext = null;
-
-  /** Context for the root [Isolate] that first run in this [_Manager]. */
-  _IsolateContext rootContext = null;
-
-  /** The top-level event loop. */
-  _EventLoop topEventLoop;
-
-  /** Whether this program is running from the command line. */
-  bool fromCommandLine;
-
-  /** Whether this [_Manager] is running as a web worker. */
-  bool isWorker;
-
-  /** Whether we support spawning web workers. */
-  bool supportsWorkers;
-
-  /**
-   * Whether to use web workers when implementing isolates. Set to false for
-   * debugging/testing.
-   */
-  bool get useWorkers => supportsWorkers;
-
-  /**
-   * Whether to use the web-worker JSON-based message serialization protocol. By
-   * default this is only used with web workers. For debugging, you can force
-   * using this protocol by changing this field value to [true].
-   */
-  bool get needSerialization => useWorkers;
-
-  /**
-   * Registry of isolates. Isolates must be registered if, and only if, receive
-   * ports are alive.  Normally no open receive-ports means that the isolate is
-   * dead, but DOM callbacks could resurrect it.
-   */
-  Map<int, _IsolateContext> isolates;
-
-  /** Reference to the main [_Manager].  Null in the main [_Manager] itself. */
-  _ManagerStub mainManager;
-
-  /** Registry of active [_ManagerStub]s.  Only used in the main [_Manager]. */
-  Map<int, _ManagerStub> managers;
-
-  _Manager() {
-    _nativeDetectEnvironment();
-    topEventLoop = new _EventLoop();
-    isolates = new Map<int, _IsolateContext>();
-    managers = new Map<int, _ManagerStub>();
-    if (isWorker) {  // "if we are not the main manager ourself" is the intent.
-      mainManager = new _MainManagerStub();
-      _nativeInitWorkerMessageHandler();
-    }
-  }
-
-  void _nativeDetectEnvironment() {
-    isWorker = JS("bool", r"$isWorker");
-    supportsWorkers = JS("bool", r"$supportsWorkers");
-    fromCommandLine = JS("bool", r"typeof(window) == 'undefined'");
-  }
-
-  void _nativeInitWorkerMessageHandler() {
-    JS("void", r"""
-$globalThis.onmessage = function (e) {
-  _IsolateNatives._processWorkerMessage(this.mainManager, e);
-}""");
-  }
-  /*: TODO: check that _processWorkerMessage is not discarded while treeshaking.
-  """ {
-    _IsolateNatives._processWorkerMessage(null, null);
-  }
-  */
-
-
-  /** Close the worker running this code if all isolates are done. */
-  void maybeCloseWorker() {
-    if (isolates.isEmpty) {
-      mainManager.postMessage(_serializeMessage({'command': 'close'}));
-    }
-  }
-}
-
-/** Context information tracked for each isolate. */
-class _IsolateContext {
-  /** Current isolate id. */
-  int id;
-
-  /** Registry of receive ports currently active on this isolate. */
-  Map<int, ReceivePort> ports;
-
-  /** Holds isolate globals (statics and top-level properties). */
-  var isolateStatics; // native object containing all globals of an isolate.
-
-  _IsolateContext() {
-    id = _globalState.nextIsolateId++;
-    ports = new Map<int, ReceivePort>();
-    initGlobals();
-  }
-
-  // these are filled lazily the first time the isolate starts running.
-  void initGlobals() { JS("void", r'$initGlobals(#)', this); }
-
-  /**
-   * Run [code] in the context of the isolate represented by [this]. Note this
-   * is called from JavaScript (see $wrap_call in corejs.dart).
-   */
-  dynamic eval(Function code) {
-    var old = _globalState.currentContext;
-    _globalState.currentContext = this;
-    this._setGlobals();
-    var result = null;
-    try {
-      result = code();
-    } finally {
-      _globalState.currentContext = old;
-      if (old != null) old._setGlobals();
-    }
-    return result;
-  }
-
-  void _setGlobals() { JS("void", r'$setGlobals(#)', this); }
-
-  /** Lookup a port registered for this isolate. */
-  ReceivePort lookup(int portId) => ports[portId];
-
-  /** Register a port on this isolate. */
-  void register(int portId, ReceivePort port)  {
-    if (ports.containsKey(portId)) {
-      throw new Exception("Registry: ports must be registered only once.");
-    }
-    ports[portId] = port;
-    _globalState.isolates[id] = this; // indicate this isolate is active
-  }
-
-  /** Unregister a port on this isolate. */
-  void unregister(int portId) {
-    ports.remove(portId);
-    if (ports.isEmpty) {
-      _globalState.isolates.remove(id); // indicate this isolate is not active
-    }
-  }
-}
-
-/** Represent the event loop on a javascript thread (DOM or worker). */
-class _EventLoop {
-  Queue<_IsolateEvent> events;
-
-  _EventLoop() : events = new Queue<_IsolateEvent>();
-
-  void enqueue(isolate, fn, msg) {
-    events.addLast(new _IsolateEvent(isolate, fn, msg));
-  }
-
-  _IsolateEvent dequeue() {
-    if (events.isEmpty) return null;
-    return events.removeFirst();
-  }
-
-  /** Process a single event, if any. */
-  bool runIteration() {
-    final event = dequeue();
-    if (event == null) {
-      if (_globalState.isWorker) {
-        _globalState.maybeCloseWorker();
-      } else if (_globalState.rootContext != null &&
-                 _globalState.isolates.containsKey(
-                     _globalState.rootContext.id) &&
-                 _globalState.fromCommandLine &&
-                 _globalState.rootContext.ports.isEmpty) {
-        // We want to reach here only on the main [_Manager] and only
-        // on the command-line.  In the browser the isolate might
-        // still be alive due to DOM callbacks, but the presumption is
-        // that on the command-line, no future events can be injected
-        // into the event queue once it's empty.  Node has setTimeout
-        // so this presumption is incorrect there.  We think(?) that
-        // in d8 this assumption is valid.
-        throw new Exception("Program exited with open ReceivePorts.");
-      }
-      return false;
-    }
-    event.process();
-    return true;
-  }
-
-  /**
-   * Runs multiple iterations of the run-loop. If possible, each iteration is
-   * run asynchronously.
-   */
-  void _runHelper() {
-    // [_window] is defined in timer_provider.dart.
-    if (_window != null) {
-      // Run each iteration from the browser's top event loop.
-      void next() {
-        if (!runIteration()) return;
-        _window.setTimeout(next, 0);
-      }
-      next();
-    } else {
-      // Run synchronously until no more iterations are available.
-      while (runIteration()) {}
-    }
-  }
-
-  /**
-   * Call [_runHelper] but ensure that worker exceptions are propragated. Note
-   * this is called from JavaScript (see $wrap_call in corejs.dart).
-   */
-  void run() {
-    if (!_globalState.isWorker) {
-      _runHelper();
-    } else {
-      try {
-        _runHelper();
-      } catch (e, trace) {
-        _globalState.mainManager.postMessage(_serializeMessage(
-            {'command': 'error', 'msg': '$e\n$trace' }));
-      }
-    }
-  }
-}
-
-/** An event in the top-level event queue. */
-class _IsolateEvent {
-  _IsolateContext isolate;
-  Function fn;
-  String message;
-
-  _IsolateEvent(this.isolate, this.fn, this.message);
-
-  void process() {
-    isolate.eval(fn);
-  }
-}
-
-/** An interface for a stub used to interact with a manager. */
-abstract class _ManagerStub {
-  get id;
-  void set id(int i);
-  void set onmessage(Function f);
-  void postMessage(msg);
-  void terminate();
-}
-
-/** A stub for interacting with the main manager. */
-class _MainManagerStub implements _ManagerStub {
-  get id => 0;
-  void set id(int i) { throw new UnimplementedError(); }
-  void set onmessage(f) {
-    throw new Exception("onmessage should not be set on MainManagerStub");
-  }
-  void postMessage(msg) { JS("void", r"$globalThis.postMessage(#)", msg); }
-  void terminate() {}  // Nothing useful to do here.
-}
-
-/**
- * A stub for interacting with a manager built on a web worker. This
- * definition uses a 'hidden' type (* prefix on the native name) to
- * enforce that the type is defined dynamically only when web workers
- * are actually available.
- */
-class _WorkerStub implements _ManagerStub native "*Worker" {
-  get id => JS("var", "#.id", this);
-  void set id(i) { JS("void", "#.id = #", this, i); }
-  void set onmessage(f) { JS("void", "#.onmessage = #", this, f); }
-  void postMessage(msg) => JS("void", "#.postMessage(#)", this, msg);
-  // terminate() is implemented by Worker.
-  void terminate();
-}
-
-const String _SPAWNED_SIGNAL = "spawned";
-
-class _IsolateNatives {
-
-  /**
-   * The src url for the script tag that loaded this code. Used to create
-   * JavaScript workers.
-   */
-  static String get _thisScript => JS("String", r"$thisScriptUrl");
-
-  /** Starts a new worker with the given URL. */
-  static _WorkerStub _newWorker(url) => JS("_WorkerStub", r"new Worker(#)", url);
-
-  /**
-   * Assume that [e] is a browser message event and extract its message data.
-   * We don't import the dom explicitly so, when workers are disabled, this
-   * library can also run on top of nodejs.
-   */
-  //static _getEventData(e) => JS("Object", "#.data", e);
-  static _getEventData(e) => JS("", "#.data", e);
-
-  /**
-   * Process messages on a worker, either to control the worker instance or to
-   * pass messages along to the isolate running in the worker.
-   */
-  static void _processWorkerMessage(sender, e) {
-    var msg = _deserializeMessage(_getEventData(e));
-    switch (msg['command']) {
-      case 'start':
-        _globalState.currentManagerId = msg['id'];
-        Function entryPoint = _getJSFunctionFromName(msg['functionName']);
-        var replyTo = _deserializeMessage(msg['replyTo']);
-        _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
-          _startIsolate(entryPoint, replyTo);
-        }, 'worker-start');
-        _globalState.topEventLoop.run();
-        break;
-      case 'spawn-worker':
-        _spawnWorker(msg['functionName'], msg['uri'], msg['replyPort']);
-        break;
-      case 'message':
-        msg['port'].send(msg['msg'], msg['replyTo']);
-        _globalState.topEventLoop.run();
-        break;
-      case 'close':
-        _log("Closing Worker");
-        _globalState.managers.remove(sender.id);
-        sender.terminate();
-        _globalState.topEventLoop.run();
-        break;
-      case 'log':
-        _log(msg['msg']);
-        break;
-      case 'print':
-        if (_globalState.isWorker) {
-          _globalState.mainManager.postMessage(
-              _serializeMessage({'command': 'print', 'msg': msg}));
-        } else {
-          print(msg['msg']);
-        }
-        break;
-      case 'error':
-        throw msg['msg'];
-    }
-  }
-
-  /** Log a message, forwarding to the main [_Manager] if appropriate. */
-  static _log(msg) {
-    if (_globalState.isWorker) {
-      _globalState.mainManager.postMessage(
-          _serializeMessage({'command': 'log', 'msg': msg }));
-    } else {
-      try {
-        _consoleLog(msg);
-      } catch (e, trace) {
-        throw new Exception(trace);
-      }
-    }
-  }
-
-  static void _consoleLog(msg) {
-    JS("void", r"$globalThis.console.log(#)", msg);
-  }
-
-  /**
-   * Extract the constructor of runnable, so it can be allocated in another
-   * isolate.
-   */
-  static dynamic _getJSConstructor(Isolate runnable) {
-    return JS("Object", "#.constructor", runnable);
-  }
-
-  /** Extract the constructor name of a runnable */
-  // TODO(sigmund): find a browser-generic way to support this.
-  // TODO(floitsch): is this function still used? If yes, should we use
-  // Primitives.objectTypeName instead?
-  static dynamic _getJSConstructorName(Isolate runnable) {
-    return JS("Object", "#.constructor.name", runnable);
-  }
-
-  /** Find a constructor given its name. */
-  static dynamic _getJSConstructorFromName(String factoryName) {
-    return JS("Object", r"$globalThis[#]", factoryName);
-  }
-
-  static dynamic _getJSFunctionFromName(String functionName) {
-    return JS("Object", r"$globalThis[#]", functionName);
-  }
-
-  /**
-   * Get a string name for the function, if possible.  The result for
-   * anonymous functions is browser-dependent -- it may be "" or "anonymous"
-   * but you should probably not count on this.
-   */
-  static String _getJSFunctionName(Function f) {
-    return JS("Object", r"(#.$name || #)", f, null);
-  }
-
-  /** Create a new JavaScript object instance given its constructor. */
-  static dynamic _allocate(var ctor) {
-    return JS("Object", "new #()", ctor);
-  }
-
-  // TODO(sigmund): clean up above, after we make the new API the default:
-
-  static _spawn(String functionName, String uri, bool isLight) {
-    Completer<SendPort> completer = new Completer<SendPort>();
-    ReceivePort port = new ReceivePort();
-    port.receive((msg, SendPort replyPort) {
-      port.close();
-      assert(msg == _SPAWNED_SIGNAL);
-      completer.complete(replyPort);
-    });
-
-    SendPort signalReply = port.toSendPort();
-
-    if (_globalState.useWorkers && !isLight) {
-      _startWorker(functionName, uri, signalReply);
-    } else {
-      _startNonWorker(functionName, uri, signalReply);
-    }
-    return new _BufferingSendPort(
-        _globalState.currentContext.id, completer.future);
-  }
-
-  static SendPort _startWorker(
-      String functionName, String uri, SendPort replyPort) {
-    if (_globalState.isWorker) {
-      _globalState.mainManager.postMessage(_serializeMessage({
-          'command': 'spawn-worker',
-          'functionName': functionName,
-          'uri': uri,
-          'replyPort': replyPort}));
-    } else {
-      _spawnWorker(functionName, uri, replyPort);
-    }
-  }
-
-  static SendPort _startNonWorker(
-      String functionName, String uri, SendPort replyPort) {
-    // TODO(eub): support IE9 using an iframe -- Dart issue 1702.
-    if (uri != null) throw new UnsupportedError(
-            "Currently spawnUri is not supported without web workers.");
-    _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
-      final func = _getJSFunctionFromName(functionName);
-      _startIsolate(func, replyPort);
-    }, 'nonworker start');
-  }
-
-  static void _startIsolate(Function topLevel, SendPort replyTo) {
-    _fillStatics(_globalState.currentContext);
-    _lazyPort = new ReceivePort();
-    replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
-
-    if (_window != null)  {
-      _globalState.currentContext.eval(
-          () => _setTimerFactoryClosure(_timerFactory));
-    }
-
-    topLevel();
-  }
-
-  /**
-   * Spawns an isolate in a worker. [factoryName] is the Javascript constructor
-   * name for the isolate entry point class.
-   */
-  static void _spawnWorker(functionName, uri, replyPort) {
-    if (functionName == null) functionName = 'main';
-    if (uri == null) uri = _thisScript;
-    if (!(new Uri.fromString(uri).isAbsolute())) {
-      // The constructor of dom workers requires an absolute URL. If we use a
-      // relative path we will get a DOM exception.
-      String prefix = _thisScript.substring(0, _thisScript.lastIndexOf('/'));
-      uri = "$prefix/$uri";
-    }
-    final worker = _newWorker(uri);
-    worker.onmessage = (e) { _processWorkerMessage(worker, e); };
-    var workerId = _globalState.nextManagerId++;
-    // We also store the id on the worker itself so that we can unregister it.
-    worker.id = workerId;
-    _globalState.managers[workerId] = worker;
-    worker.postMessage(_serializeMessage({
-      'command': 'start',
-      'id': workerId,
-      // Note: we serialize replyPort twice because the child worker needs to
-      // first deserialize the worker id, before it can correctly deserialize
-      // the port (port deserialization is sensitive to what is the current
-      // workerId).
-      'replyTo': _serializeMessage(replyPort),
-      'functionName': functionName }));
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/ports.dart
- ********************************************************/
-
-/** Common functionality to all send ports. */
-class _BaseSendPort implements SendPort {
-  /** Id for the destination isolate. */
-  final int _isolateId;
-
-  const _BaseSendPort(this._isolateId);
-
-  void _checkReplyTo(SendPort replyTo) {
-    if (replyTo != null
-        && replyTo is! _NativeJsSendPort
-        && replyTo is! _WorkerSendPort
-        && replyTo is! _BufferingSendPort) {
-      throw new Exception("SendPort.send: Illegal replyTo port type");
-    }
-  }
-
-  Future call(var message) {
-    final completer = new Completer();
-    final port = new _ReceivePortImpl();
-    send(message, port.toSendPort());
-    port.receive((value, ignoreReplyTo) {
-      port.close();
-      if (value is Exception) {
-        completer.completeException(value);
-      } else {
-        completer.complete(value);
-      }
-    });
-    return completer.future;
-  }
-
-  void send(var message, [SendPort replyTo]);
-  bool operator ==(var other);
-  int get hashCode;
-}
-
-/** A send port that delivers messages in-memory via native JavaScript calls. */
-class _NativeJsSendPort extends _BaseSendPort implements SendPort {
-  final _ReceivePortImpl _receivePort;
-
-  const _NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId);
-
-  void send(var message, [SendPort replyTo = null]) {
-    _waitForPendingPorts([message, replyTo], () {
-      _checkReplyTo(replyTo);
-      // Check that the isolate still runs and the port is still open
-      final isolate = _globalState.isolates[_isolateId];
-      if (isolate == null) return;
-      if (_receivePort._callback == null) return;
-
-      // We force serialization/deserialization as a simple way to ensure
-      // isolate communication restrictions are respected between isolates that
-      // live in the same worker. [_NativeJsSendPort] delivers both messages
-      // from the same worker and messages from other workers. In particular,
-      // messages sent from a worker via a [_WorkerSendPort] are received at
-      // [_processWorkerMessage] and forwarded to a native port. In such cases,
-      // here we'll see [_globalState.currentContext == null].
-      final shouldSerialize = _globalState.currentContext != null
-          && _globalState.currentContext.id != _isolateId;
-      var msg = message;
-      var reply = replyTo;
-      if (shouldSerialize) {
-        msg = _serializeMessage(msg);
-        reply = _serializeMessage(reply);
-      }
-      _globalState.topEventLoop.enqueue(isolate, () {
-        if (_receivePort._callback != null) {
-          if (shouldSerialize) {
-            msg = _deserializeMessage(msg);
-            reply = _deserializeMessage(reply);
-          }
-          _receivePort._callback(msg, reply);
-        }
-      }, 'receive $message');
-    });
-  }
-
-  bool operator ==(var other) => (other is _NativeJsSendPort) &&
-      (_receivePort == other._receivePort);
-
-  int get hashCode => _receivePort._id;
-}
-
-/** A send port that delivers messages via worker.postMessage. */
-// TODO(eub): abstract this for iframes.
-class _WorkerSendPort extends _BaseSendPort implements SendPort {
-  final int _workerId;
-  final int _receivePortId;
-
-  const _WorkerSendPort(this._workerId, int isolateId, this._receivePortId)
-      : super(isolateId);
-
-  void send(var message, [SendPort replyTo = null]) {
-    _waitForPendingPorts([message, replyTo], () {
-      _checkReplyTo(replyTo);
-      final workerMessage = _serializeMessage({
-          'command': 'message',
-          'port': this,
-          'msg': message,
-          'replyTo': replyTo});
-
-      if (_globalState.isWorker) {
-        // communication from one worker to another go through the main worker:
-        _globalState.mainManager.postMessage(workerMessage);
-      } else {
-        _globalState.managers[_workerId].postMessage(workerMessage);
-      }
-    });
-  }
-
-  bool operator ==(var other) {
-    return (other is _WorkerSendPort) &&
-        (_workerId == other._workerId) &&
-        (_isolateId == other._isolateId) &&
-        (_receivePortId == other._receivePortId);
-  }
-
-  int get hashCode {
-    // TODO(sigmund): use a standard hash when we get one available in corelib.
-    return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId;
-  }
-}
-
-/** A port that buffers messages until an underlying port gets resolved. */
-class _BufferingSendPort extends _BaseSendPort implements SendPort {
-  /** Internal counter to assign unique ids to each port. */
-  static int _idCount = 0;
-
-  /** For implementing equals and hashcode. */
-  final int _id;
-
-  /** Underlying port, when resolved. */
-  SendPort _port;
-
-  /**
-   * Future of the underlying port, so that we can detect when this port can be
-   * sent on messages.
-   */
-  Future<SendPort> _futurePort;
-
-  /** Pending messages (and reply ports). */
-  List pending;
-
-  _BufferingSendPort(isolateId, this._futurePort)
-      : super(isolateId), _id = _idCount, pending = [] {
-    _idCount++;
-    _futurePort.then((p) {
-      _port = p;
-      for (final item in pending) {
-        p.send(item['message'], item['replyTo']);
-      }
-      pending = null;
-    });
-  }
-
-  _BufferingSendPort.fromPort(isolateId, this._port)
-      : super(isolateId), _id = _idCount {
-    _idCount++;
-  }
-
-  void send(var message, [SendPort replyTo]) {
-    if (_port != null) {
-      _port.send(message, replyTo);
-    } else {
-      pending.add({'message': message, 'replyTo': replyTo});
-    }
-  }
-
-  bool operator ==(var other) =>
-      other is _BufferingSendPort && _id == other._id;
-  int get hashCode => _id;
-}
 
 /** Default factory for receive ports. */
 patch class ReceivePort {
   patch factory ReceivePort() {
-    return new _ReceivePortImpl();
-  }
-
-}
-
-/** Implementation of a multi-use [ReceivePort] on top of JavaScript. */
-class _ReceivePortImpl implements ReceivePort {
-  int _id;
-  Function _callback;
-  static int _nextFreeId = 1;
-
-  _ReceivePortImpl()
-      : _id = _nextFreeId++ {
-    _globalState.currentContext.register(_id, this);
-  }
-
-  void receive(void onMessage(var message, SendPort replyTo)) {
-    _callback = onMessage;
-  }
-
-  void close() {
-    _callback = null;
-    _globalState.currentContext.unregister(_id);
-  }
-
-  SendPort toSendPort() {
-    return new _NativeJsSendPort(this, _globalState.currentContext.id);
+    return new ReceivePortImpl();
   }
 }
 
-/** Wait until all ports in a message are resolved. */
-_waitForPendingPorts(var message, void callback()) {
-  final finder = new _PendingSendPortFinder();
-  finder.traverse(message);
-  Futures.wait(finder.ports).then((_) => callback());
-}
-
-
-/** Visitor that finds all unresolved [SendPort]s in a message. */
-class _PendingSendPortFinder extends _MessageTraverser {
-  List<Future<SendPort>> ports;
-  _PendingSendPortFinder() : super(), ports = [] {
-    _visited = new _JsVisitedMap();
-  }
-
-  visitPrimitive(x) {}
-
-  visitList(List list) {
-    final seen = _visited[list];
-    if (seen != null) return;
-    _visited[list] = true;
-    // TODO(sigmund): replace with the following: (bug #1660)
-    // list.forEach(_dispatch);
-    list.forEach((e) => _dispatch(e));
-  }
-
-  visitMap(Map map) {
-    final seen = _visited[map];
-    if (seen != null) return;
-
-    _visited[map] = true;
-    // TODO(sigmund): replace with the following: (bug #1660)
-    // map.values.forEach(_dispatch);
-    map.values.forEach((e) => _dispatch(e));
-  }
-
-  visitSendPort(SendPort port) {
-    if (port is _BufferingSendPort && port._port == null) {
-      ports.add(port._futurePort);
+patch class Timer {
+  patch factory Timer(int milliseconds, void callback(Timer timer)) {
+    if (!hasWindow()) {
+      throw new UnsupportedError("Timer interface not supported.");
     }
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/messages.dart
- ********************************************************/
-
-// Defines message visitors, serialization, and deserialization.
-
-/** Serialize [message] (or simulate serialization). */
-_serializeMessage(message) {
-  if (_globalState.needSerialization) {
-    return new _JsSerializer().traverse(message);
-  } else {
-    return new _JsCopier().traverse(message);
-  }
-}
-
-/** Deserialize [message] (or simulate deserialization). */
-_deserializeMessage(message) {
-  if (_globalState.needSerialization) {
-    return new _JsDeserializer().deserialize(message);
-  } else {
-    // Nothing more to do.
-    return message;
-  }
-}
-
-class _JsSerializer extends _Serializer {
-
-  _JsSerializer() : super() { _visited = new _JsVisitedMap(); }
-
-  visitSendPort(SendPort x) {
-    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
-    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
-    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
-    throw "Illegal underlying port $x";
+    return new TimerImpl(milliseconds, callback);
   }
 
-  visitNativeJsSendPort(_NativeJsSendPort port) {
-    return ['sendport', _globalState.currentManagerId,
-        port._isolateId, port._receivePort._id];
-  }
-
-  visitWorkerSendPort(_WorkerSendPort port) {
-    return ['sendport', port._workerId, port._isolateId, port._receivePortId];
-  }
-
-  visitBufferingSendPort(_BufferingSendPort port) {
-    if (port._port != null) {
-      return visitSendPort(port._port);
-    } else {
-      // TODO(floitsch): Use real exception (which one?).
-      throw
-          "internal error: must call _waitForPendingPorts to ensure all"
-          " ports are resolved at this point.";
+  /**
+   * Creates a new repeating timer. The [callback] is invoked every
+   * [milliseconds] millisecond until cancelled.
+   */
+  patch factory Timer.repeating(int milliseconds, void callback(Timer timer)) {
+    if (!hasWindow()) {
+      throw new UnsupportedError("Timer interface not supported.");
     }
-  }
-
-}
-
-
-class _JsCopier extends _Copier {
-
-  _JsCopier() : super() { _visited = new _JsVisitedMap(); }
-
-  visitSendPort(SendPort x) {
-    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
-    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
-    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
-    throw "Illegal underlying port $p";
-  }
-
-  SendPort visitNativeJsSendPort(_NativeJsSendPort port) {
-    return new _NativeJsSendPort(port._receivePort, port._isolateId);
-  }
-
-  SendPort visitWorkerSendPort(_WorkerSendPort port) {
-    return new _WorkerSendPort(
-        port._workerId, port._isolateId, port._receivePortId);
-  }
-
-  SendPort visitBufferingSendPort(_BufferingSendPort port) {
-    if (port._port != null) {
-      return visitSendPort(port._port);
-    } else {
-      // TODO(floitsch): Use real exception (which one?).
-      throw
-          "internal error: must call _waitForPendingPorts to ensure all"
-          " ports are resolved at this point.";
-    }
-  }
-
-}
-
-class _JsDeserializer extends _Deserializer {
-
-  SendPort deserializeSendPort(List x) {
-    int managerId = x[1];
-    int isolateId = x[2];
-    int receivePortId = x[3];
-    // If two isolates are in the same manager, we use NativeJsSendPorts to
-    // deliver messages directly without using postMessage.
-    if (managerId == _globalState.currentManagerId) {
-      var isolate = _globalState.isolates[isolateId];
-      if (isolate == null) return null; // Isolate has been closed.
-      var receivePort = isolate.lookup(receivePortId);
-      return new _NativeJsSendPort(receivePort, isolateId);
-    } else {
-      return new _WorkerSendPort(managerId, isolateId, receivePortId);
-    }
-  }
-
-}
-
-class _JsVisitedMap implements _MessageTraverserVisitedMap {
-  List tagged;
-
-  /** Retrieves any information stored in the native object [object]. */
-  operator[](var object) {
-    return _getAttachedInfo(object);
-  }
-
-  /** Injects some information into the native [object]. */
-  void operator[]=(var object, var info) {
-    tagged.add(object);
-    _setAttachedInfo(object, info);
-  }
-
-  /** Get ready to rumble. */
-  void reset() {
-    assert(tagged == null);
-    tagged = new List();
-  }
-
-  /** Remove all information injected in the native objects. */
-  void cleanup() {
-    for (int i = 0, length = tagged.length; i < length; i++) {
-      _clearAttachedInfo(tagged[i]);
-    }
-    tagged = null;
-  }
-
-  void _clearAttachedInfo(var o) {
-    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, null);
-  }
-
-  void _setAttachedInfo(var o, var info) {
-    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, info);
-  }
-
-  _getAttachedInfo(var o) {
-    return JS("", "#['__MessageTraverser__attached_info__']", o);
+    return new TimerImpl.repeating(milliseconds, callback);
   }
 }
-
-// only visible for testing purposes
-// TODO(sigmund): remove once we can disable privacy for testing (bug #1882)
-class TestingOnly {
-  static copy(x) {
-    return new _JsCopier().traverse(x);
-  }
-
-  // only visible for testing purposes
-  static serialize(x) {
-    _Serializer serializer = new _JsSerializer();
-    _Deserializer deserializer = new _JsDeserializer();
-    return deserializer.deserialize(serializer.traverse(x));
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/serialization.dart
- ********************************************************/
-
-class _MessageTraverserVisitedMap {
-
-  operator[](var object) => null;
-  void operator[]=(var object, var info) { }
-
-  void reset() { }
-  void cleanup() { }
-
-}
-
-/** Abstract visitor for dart objects that can be sent as isolate messages. */
-class _MessageTraverser {
-
-  _MessageTraverserVisitedMap _visited;
-  _MessageTraverser() : _visited = new _MessageTraverserVisitedMap();
-
-  /** Visitor's entry point. */
-  traverse(var x) {
-    if (isPrimitive(x)) return visitPrimitive(x);
-    _visited.reset();
-    var result;
-    try {
-      result = _dispatch(x);
-    } finally {
-      _visited.cleanup();
-    }
-    return result;
-  }
-
-  _dispatch(var x) {
-    if (isPrimitive(x)) return visitPrimitive(x);
-    if (x is List) return visitList(x);
-    if (x is Map) return visitMap(x);
-    if (x is SendPort) return visitSendPort(x);
-    if (x is SendPortSync) return visitSendPortSync(x);
-
-    // Overridable fallback.
-    return visitObject(x);
-  }
-
-  visitPrimitive(x);
-  visitList(List x);
-  visitMap(Map x);
-  visitSendPort(SendPort x);
-  visitSendPortSync(SendPortSync x);
-
-  visitObject(Object x) {
-    // TODO(floitsch): make this a real exception. (which one)?
-    throw "Message serialization: Illegal value $x passed";
-  }
-
-  static bool isPrimitive(x) {
-    return (x == null) || (x is String) || (x is num) || (x is bool);
-  }
-}
-
-
-/** A visitor that recursively copies a message. */
-class _Copier extends _MessageTraverser {
-
-  visitPrimitive(x) => x;
-
-  List visitList(List list) {
-    List copy = _visited[list];
-    if (copy != null) return copy;
-
-    int len = list.length;
-
-    // TODO(floitsch): we loose the generic type of the List.
-    copy = new List(len);
-    _visited[list] = copy;
-    for (int i = 0; i < len; i++) {
-      copy[i] = _dispatch(list[i]);
-    }
-    return copy;
-  }
-
-  Map visitMap(Map map) {
-    Map copy = _visited[map];
-    if (copy != null) return copy;
-
-    // TODO(floitsch): we loose the generic type of the map.
-    copy = new Map();
-    _visited[map] = copy;
-    map.forEach((key, val) {
-      copy[_dispatch(key)] = _dispatch(val);
-    });
-    return copy;
-  }
-
-}
-
-/** Visitor that serializes a message as a JSON array. */
-class _Serializer extends _MessageTraverser {
-  int _nextFreeRefId = 0;
-
-  visitPrimitive(x) => x;
-
-  visitList(List list) {
-    int copyId = _visited[list];
-    if (copyId != null) return ['ref', copyId];
-
-    int id = _nextFreeRefId++;
-    _visited[list] = id;
-    var jsArray = _serializeList(list);
-    // TODO(floitsch): we are losing the generic type.
-    return ['list', id, jsArray];
-  }
-
-  visitMap(Map map) {
-    int copyId = _visited[map];
-    if (copyId != null) return ['ref', copyId];
-
-    int id = _nextFreeRefId++;
-    _visited[map] = id;
-    var keys = _serializeList(map.keys);
-    var values = _serializeList(map.values);
-    // TODO(floitsch): we are losing the generic type.
-    return ['map', id, keys, values];
-  }
-
-  _serializeList(List list) {
-    int len = list.length;
-    var result = new List(len);
-    for (int i = 0; i < len; i++) {
-      result[i] = _dispatch(list[i]);
-    }
-    return result;
-  }
-}
-
-/** Deserializes arrays created with [_Serializer]. */
-class _Deserializer {
-  Map<int, dynamic> _deserialized;
-
-  _Deserializer();
-
-  static bool isPrimitive(x) {
-    return (x == null) || (x is String) || (x is num) || (x is bool);
-  }
-
-  deserialize(x) {
-    if (isPrimitive(x)) return x;
-    // TODO(floitsch): this should be new HashMap<int, var|Dynamic>()
-    _deserialized = new HashMap();
-    return _deserializeHelper(x);
-  }
-
-  _deserializeHelper(x) {
-    if (isPrimitive(x)) return x;
-    assert(x is List);
-    switch (x[0]) {
-      case 'ref': return _deserializeRef(x);
-      case 'list': return _deserializeList(x);
-      case 'map': return _deserializeMap(x);
-      case 'sendport': return deserializeSendPort(x);
-      default: return deserializeObject(x);
-    }
-  }
-
-  _deserializeRef(List x) {
-    int id = x[1];
-    var result = _deserialized[id];
-    assert(result != null);
-    return result;
-  }
-
-  List _deserializeList(List x) {
-    int id = x[1];
-    // We rely on the fact that Dart-lists are directly mapped to Js-arrays.
-    List dartList = x[2];
-    _deserialized[id] = dartList;
-    int len = dartList.length;
-    for (int i = 0; i < len; i++) {
-      dartList[i] = _deserializeHelper(dartList[i]);
-    }
-    return dartList;
-  }
-
-  Map _deserializeMap(List x) {
-    Map result = new Map();
-    int id = x[1];
-    _deserialized[id] = result;
-    List keys = x[2];
-    List values = x[3];
-    int len = keys.length;
-    assert(len == values.length);
-    for (int i = 0; i < len; i++) {
-      var key = _deserializeHelper(keys[i]);
-      var value = _deserializeHelper(values[i]);
-      result[key] = value;
-    }
-    return result;
-  }
-
-  deserializeSendPort(List x);
-
-  deserializeObject(List x) {
-    // TODO(floitsch): Use real exception (which one?).
-    throw "Unexpected serialized object";
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/timer_provider.dart
- ********************************************************/
-
-// We don't want to import the DOM library just because of window.setTimeout,
-// so we reconstruct the Window class here. The only conflict that could happen
-// with the other DOMWindow class would be because of subclasses.
-// Currently, none of the two Dart classes have subclasses.
-typedef void _TimeoutHandler();
-
-class _Window native "@*DOMWindow" {
-  int setTimeout(_TimeoutHandler handler, int timeout) native;
-  int setInterval(_TimeoutHandler handler, int timeout) native;
-  void clearTimeout(int handle) native;
-  void clearInterval(int handle) native;
-}
-
-_Window get _window =>
-  JS('bool', 'typeof window != "undefined"') ? JS('_Window', 'window') : null;
-
-class _Timer implements Timer {
-  final bool _once;
-  int _handle;
-
-  _Timer(int milliSeconds, void callback(Timer timer))
-      : _once = true {
-    _handle = _window.setTimeout(() => callback(this), milliSeconds);
-  }
-
-  _Timer.repeating(int milliSeconds, void callback(Timer timer))
-      : _once = false {
-    _handle = _window.setInterval(() => callback(this), milliSeconds);
-  }
-
-  void cancel() {
-    if (_once) {
-      _window.clearTimeout(_handle);
-    } else {
-      _window.clearInterval(_handle);
-    }
-  }
-}
-
-Timer _timerFactory(int millis, void callback(Timer timer), bool repeating) =>
-  repeating ? new _Timer.repeating(millis, callback)
-            : new _Timer(millis, callback);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/mirror_opt_in_message.dart b/sdk/lib/_internal/compiler/implementation/lib/mirror_opt_in_message.dart
index df196a2..b9743de 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/mirror_opt_in_message.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/mirror_opt_in_message.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+part of _js_helper;
+
 // Yeah, seriously: mirrors in dart2js are experimental...
 const String MIRROR_OPT_IN_MESSAGE = """
 
diff --git a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
index 46d81be..f6f88c7 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
@@ -2,24 +2,21 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+part of _js_helper;
+
 String typeNameInChrome(obj) {
   String name = JS('String', "#.constructor.name", obj);
-  if (name == 'Window') return 'DOMWindow';
-  if (name == 'CanvasPixelArray') return 'Uint8ClampedArray';
-  if (name == 'WebKitMutationObserver') return 'MutationObserver';
-  if (name == 'AudioChannelMerger') return 'ChannelMergerNode';
-  if (name == 'AudioChannelSplitter') return 'ChannelSplitterNode';
-  if (name == 'AudioGainNode') return 'GainNode';
-  if (name == 'AudioPannerNode') return 'PannerNode';
-  if (name == 'JavaScriptAudioNode') return 'ScriptProcessorNode';
-  if (name == 'Oscillator') return 'OscillatorNode';
-  if (name == 'RealtimeAnalyserNode') return 'AnalyserNode';
-  return name;
+  return typeNameInWebKitCommon(name);
 }
 
 String typeNameInSafari(obj) {
   String name = JS('String', '#', constructorNameFallback(obj));
   // Safari is very similar to Chrome.
+  return typeNameInWebKitCommon(name);
+}
+
+String typeNameInWebKitCommon(tag) {
+  String name = JS('String', '#', tag);
   if (name == 'Window') return 'DOMWindow';
   if (name == 'CanvasPixelArray') return 'Uint8ClampedArray';
   if (name == 'WebKitMutationObserver') return 'MutationObserver';
@@ -100,6 +97,23 @@
   return JS('String', '#.substring(8, # - 1)', string, string.length);
 }
 
+/**
+ * If a lookup on an object [object] that has [tag] fails, this function is
+ * called to provide an alternate tag.  This allows us to fail gracefully if we
+ * can make a good guess, for example, when browsers add novel kinds of
+ * HTMLElement that we have never heard of.
+ */
+String alternateTag(object, String tag) {
+  // Does it smell like some kind of HTML element?
+  if (JS('bool', r'!!/^HTML[A-Z].*Element$/.test(#)', tag)) {
+    // Check that it is not a simple JavaScript object.
+    String string = JS('String', 'Object.prototype.toString.call(#)', object);
+    if (string == '[object Object]') return null;
+    return 'HTMLElement';
+  }
+  return null;
+}
+
 // TODO(ngeoffray): stop using this method once our optimizers can
 // change str1.contains(str2) into str1.indexOf(str2) != -1.
 bool contains(String userAgent, String name) {
@@ -122,10 +136,18 @@
   return JS('var', '#[#]', object, property);
 }
 
+bool callHasOwnProperty(var function, var object, String property) {
+  return JS('bool', '#.call(#, #)', function, object, property);
+}
+
 void propertySet(var object, String property, var value) {
   JS('var', '#[#] = #', object, property, value);
 }
 
+getPropertyFromPrototype(var object, String name) {
+  return JS('var', 'Object.getPrototypeOf(#)[#]', object, name);
+}
+
 newJsObject() {
   return JS('var', '{}');
 }
@@ -183,8 +205,9 @@
  * Sets a JavaScript property on an object.
  */
 void defineProperty(var obj, String property, var value) {
-  JS('void', """Object.defineProperty(#, #,
-      {value: #, enumerable: false, writable: true, configurable: true})""",
+  JS('void',
+      'Object.defineProperty(#, #, '
+          '{value: #, enumerable: false, writable: true, configurable: true})',
       obj,
       property,
       value);
@@ -205,21 +228,26 @@
             String name,
             var methods,
             List arguments) {
+  // The tag is related to the class name.  E.g. the dart:html class
+  // '_ButtonElement' has the tag 'HTMLButtonElement'.  TODO(erikcorry): rename
+  // getTypeNameOf to getTypeTag.
   String tag = getTypeNameOf(obj);
-  var method = JS('var', '#[#]', methods, tag);
+  var hasOwnPropertyFunction = JS('var', 'Object.prototype.hasOwnProperty');
 
-  if (method == null && _dynamicMetadata != null) {
-    for (int i = 0; i < arrayLength(_dynamicMetadata); i++) {
-      MetaInfo entry = arrayGet(_dynamicMetadata, i);
-      if (JS('bool', '#', propertyGet(entry._set, tag))) {
-        method = propertyGet(methods, entry._tag);
-        if (method != null) break;
-      }
+  var method = dynamicBindLookup(hasOwnPropertyFunction, tag, methods);
+  if (method == null) {
+    String secondTag = alternateTag(obj, tag);
+    if (secondTag != null) {
+      method = dynamicBindLookup(hasOwnPropertyFunction, secondTag, methods);
     }
   }
 
+  // If we didn't find the method then look up in the Dart Object class, using
+  // getTypeNameOf in case the minifier has renamed Object.
   if (method == null) {
-    method = propertyGet(methods, 'Object');
+    String nameOfObjectClass = getTypeNameOf(const Object());
+    method =
+        lookupDynamicClass(hasOwnPropertyFunction, methods, nameOfObjectClass);
   }
 
   var proto = JS('var', 'Object.getPrototypeOf(#)', obj);
@@ -239,13 +267,44 @@
       proto, name, name);
   }
 
-  if (JS('bool', '!#.hasOwnProperty(#)', proto, name)) {
+  if (!callHasOwnProperty(hasOwnPropertyFunction, proto, name)) {
     defineProperty(proto, name, method);
   }
 
   return JS('var', '#.apply(#, #)', method, obj, arguments);
 }
 
+dynamicBindLookup(var hasOwnPropertyFunction, String tag, var methods) {
+  var method = lookupDynamicClass(hasOwnPropertyFunction, methods, tag);
+  // Look at the inheritance data, getting the class tags and using them
+  // to check the methods table for this method name.
+  if (method == null && _dynamicMetadata != null) {
+    for (int i = 0; i < arrayLength(_dynamicMetadata); i++) {
+      MetaInfo entry = arrayGet(_dynamicMetadata, i);
+      if (callHasOwnProperty(hasOwnPropertyFunction, entry._set, tag)) {
+        method =
+            lookupDynamicClass(hasOwnPropertyFunction, methods, entry._tag);
+        // Stop if we found it in the methods array.
+        if (method != null) break;
+      }
+    }
+  }
+  return method;
+}
+
+// For each method name and class inheritance subtree, we use an ordinary JS
+// object as a hash map to store the method for each class.  Entries are added
+// in native_emitter.dart (see dynamicName).  In order to avoid the class names
+// clashing with the method names on Object.prototype (needed for native
+// objects) we must always use hasOwnProperty.
+var lookupDynamicClass(var hasOwnPropertyFunction,
+                       var methods,
+                       String className) {
+  return callHasOwnProperty(hasOwnPropertyFunction, methods, className) ?
+         propertyGet(methods, className) :
+         null;
+}
+
 /**
  * Code for doing the dynamic dispatch on JavaScript prototypes that are not
  * available at compile-time. Each property of a native Dart class
@@ -273,7 +332,9 @@
   var methods = JS('var', '{}');
   // If there is a method attached to the Dart Object class, use it as
   // the method to call in case no method is registered for that type.
-  var dartMethod = JS('var', 'Object.getPrototypeOf(#)[#]', const Object(), name);
+  var dartMethod = getPropertyFromPrototype(const Object(), name);
+  // Take the method from the Dart Object class if we didn't find it yet and it
+  // is there.
   if (dartMethod != null) propertySet(methods, 'Object', dartMethod);
 
   var bind = JS('var',
diff --git a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
index 441512e..336664e 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+part of _js_helper;
+
 List regExpExec(JSSyntaxRegExp regExp, String str) {
   var nativeRegExp = regExpGetNative(regExp);
   var result = JS('=List', r'#.exec(#)', nativeRegExp, str);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
index e3da2be..8c36382 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+part of _js_helper;
+
 class StringMatch implements Match {
   const StringMatch(int this.start,
                     String this.str,
diff --git a/sdk/lib/_internal/compiler/implementation/library_loader.dart b/sdk/lib/_internal/compiler/implementation/library_loader.dart
index 6a247e2..3472b3e 100644
--- a/sdk/lib/_internal/compiler/implementation/library_loader.dart
+++ b/sdk/lib/_internal/compiler/implementation/library_loader.dart
@@ -268,7 +268,22 @@
     Script sourceScript = compiler.readScript(path, part);
     CompilationUnitElement unit =
         new CompilationUnitElement(sourceScript, library);
-    compiler.withCurrentElement(unit, () => compiler.scanner.scan(unit));
+    compiler.withCurrentElement(unit, () {
+      compiler.scanner.scan(unit);
+      if (unit.partTag == null) {
+        bool wasDiagnosticEmitted = false;
+        compiler.withCurrentElement(library, () {
+          wasDiagnosticEmitted =
+              compiler.onDeprecatedFeature(part, 'missing part-of tag');
+        });
+        if (wasDiagnosticEmitted) {
+          compiler.reportMessage(
+              compiler.spanFromElement(unit),
+              MessageKind.MISSING_PART_OF_TAG.error([]),
+              api.Diagnostic.INFO);
+        }
+      }
+    });
   }
 
   /**
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index 8a68eb5..398d641 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -199,7 +199,7 @@
     throw 'unimplemented';
   }
 
-  void onDeprecatedFeature(Spannable span, String feature) {
+  bool onDeprecatedFeature(Spannable span, String feature) {
     // TODO(johnniwinther): implement this?
     throw 'unimplemented';
   }
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 825069e..0d30ecd 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -34,6 +34,7 @@
 class NativeEnqueuer {
   /// Initial entry point to native enqueuer.
   void processNativeClasses(Collection<LibraryElement> libraries) {}
+  void processNativeClassesInLibrary(LibraryElement library) {}
 
   /// Notification of a main Enqueuer worklist element.  For methods, adds
   /// information from metadata attributes, and computes types instantiated due
@@ -452,7 +453,6 @@
   String libraryName = uri.toString();
   if (library.entryCompilationUnit.script.name.contains(
           'dart/tests/compiler/dart2js_native')
-      || libraryName == 'dart:isolate'
       || libraryName == 'dart:html'
       || libraryName == 'dart:html_common'
       || libraryName == 'dart:indexed_db'
@@ -794,19 +794,6 @@
   Compiler compiler = builder.compiler;
   FunctionElement element = builder.work.element;
   NativeEmitter nativeEmitter = builder.emitter.nativeEmitter;
-  // If what we're compiling is a getter named 'typeName' and the native
-  // class is named 'DOMType', we generate a call to the typeNameOf
-  // function attached on the isolate.
-  // The DOM classes assume that their 'typeName' property, which is
-  // not a JS property on the DOM types, returns the type name.
-  if (element.name == const SourceString('typeName')
-      && element.isGetter()
-      && nativeEmitter.toNativeName(element.getEnclosingClass()) == 'DOMType') {
-    Element helper =
-        compiler.findHelper(const SourceString('getTypeNameOf'));
-    builder.pushInvokeHelper1(helper, builder.localsHandler.readThis());
-    builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit);
-  }
 
   HInstruction convertDartClosure(Element parameter, FunctionType type) {
     HInstruction local = builder.localsHandler.readLocal(parameter);
@@ -823,14 +810,14 @@
 
   // Check which pattern this native method follows:
   // 1) foo() native;
-  //      hasBody = false, isRedirecting = false
+  //      hasBody = false
   // 2) foo() native "bar";
-  //      hasBody = false, isRedirecting = true, no longer supported.
+  //      No longer supported, this is now done with @JSName('foo') and case 1.
   // 3) foo() native "return 42";
-  //      hasBody = true, isRedirecting = false
+  //      hasBody = true
   bool hasBody = false;
   assert(element.isNative());
-  String nativeMethodName = element.nativeName();
+  String nativeMethodName = element.fixedBackendName();
   if (nativeBody != null) {
     LiteralString jsCode = nativeBody.asLiteralString();
     String str = jsCode.dartString.slowToString();
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 6202dfb..e944505 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -413,6 +413,11 @@
     }));
   }
 
+  // TODO(johnniwinther): Remove this queue when resolution has been split into
+  // syntax and semantic resolution.
+  ClassElement currentlyResolvedClass;
+  Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
+
   /**
    * Resolve the class [element].
    *
@@ -425,6 +430,26 @@
    * [:element.ensureResolved(compiler):].
    */
   void resolveClass(ClassElement element) {
+    ClassElement previousResolvedClass = currentlyResolvedClass;
+    currentlyResolvedClass = element;
+    resolveClassInternal(element);
+    if (previousResolvedClass == null) {
+      while (!pendingClassesToBeResolved.isEmpty) {
+        pendingClassesToBeResolved.removeFirst().ensureResolved(compiler);
+      }
+    }
+    currentlyResolvedClass = previousResolvedClass;
+  }
+
+  void _ensureClassWillBeResolved(ClassElement element) {
+    if (currentlyResolvedClass == null) {
+      element.ensureResolved(compiler);
+    } else {
+      pendingClassesToBeResolved.add(element);
+    }
+  }
+
+  void resolveClassInternal(ClassElement element) {
     if (!element.isPatch) {
       compiler.withCurrentElement(element, () => measure(() {
         assert(element.resolutionState == STATE_NOT_STARTED);
@@ -492,12 +517,42 @@
             MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS.error([mismatchedFlags]),
             Diagnostic.ERROR);
         }
+        checkConstructorNameHack(holder, member);
       }
       checkAbstractField(member);
       checkValidOverride(member, cls.lookupSuperMember(member.name));
     });
   }
 
+  // TODO(ahe): Remove this method.  It is only needed while we store
+  // constructor names as ClassName$id.  Once we start storing
+  // constructors as just id, this will be caught by the general
+  // mechanism for duplicate members.
+  /// Check that a constructor name does not conflict with a member.
+  void checkConstructorNameHack(ClassElement holder, FunctionElement member) {
+    // If the name of the constructor is the same as the name of the
+    // class, there cannot be a problem.
+    if (member.name == holder.name) return;
+
+    SourceString name =
+      Elements.deconstructConstructorName(member.name, holder);
+
+    // If the name could not be deconstructed, this is is from a
+    // factory method from a deprecated interface implementation.
+    if (name == null) return;
+
+    Element otherMember = holder.lookupLocalMember(name);
+    if (otherMember != null) {
+      if (compiler.onDeprecatedFeature(member, 'conflicting constructor')) {
+        compiler.reportMessage(
+            compiler.spanFromElement(otherMember),
+            MessageKind.GENERIC.error(['This member conflicts with a'
+                                       ' constructor.']),
+            Diagnostic.INFO);
+      }
+    }
+  }
+
   void checkAbstractField(Element member) {
     // Only check for getters. The test can only fail if there is both a setter
     // and a getter with the same name, and we only need to check each abstract
@@ -1153,7 +1208,8 @@
         type = checkNoTypeArguments(element.computeType(compiler));
       } else if (element.isClass()) {
         ClassElement cls = element;
-        cls.ensureResolved(compiler);
+        compiler.resolver._ensureClassWillBeResolved(cls);
+        element.computeType(compiler);
         var arguments = new LinkBuilder<DartType>();
         bool hashTypeArgumentMismatch = resolveTypeArguments(
             node, cls.typeVariables, enclosingElement,
@@ -2070,7 +2126,7 @@
         new VariableDefinitionsVisitor(compiler, node, this,
                                        ElementKind.VARIABLE);
     // Ensure that we set the type of the [VariableListElement] since it depends
-    // the current scope. If the current scope is a [MethodScope] or
+    // on the current scope. If the current scope is a [MethodScope] or
     // [BlockScope] it will not be available for the
     // [VariableListElement.computeType] method.
     if (node.type != null) {
@@ -2538,8 +2594,7 @@
       TypeVariableElement variableElement = typeVariable.element;
       if (typeNode.bound != null) {
         DartType boundType = typeResolver.resolveTypeAnnotation(
-            typeNode.bound, scope, element,
-            onFailure: warning);
+            typeNode.bound, scope, element, onFailure: warning);
         if (boundType != null && boundType.element == variableElement) {
           // TODO(johnniwinther): Check for more general cycles, like
           // [: <A extends B, B extends C, C extends B> :].
@@ -2612,14 +2667,22 @@
     resolveTypeVariableBounds(node.typeParameters);
 
     // Find super type.
-    DartType supertype = visit(node.superclass);
-    if (supertype != null && supertype.element.isExtendable()) {
-      element.supertype = supertype;
-      if (isBlackListed(supertype)) {
+    DartType supertype = null;
+    if (node.superclass != null) {
+      supertype = typeResolver.resolveTypeAnnotation(node.superclass, scope,
+          element, onFailure: error);
+    }
+    if (supertype != null) {
+      if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
+        // Error has already been reported.
+      } else if (!identical(supertype.kind, TypeKind.INTERFACE)) {
+        // TODO(johnniwinther): Handle dynamic.
+        error(node.superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
+      } else if (isBlackListed(supertype)) {
         error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
+      } else {
+        element.supertype = supertype;
       }
-    } else if (supertype != null) {
-      error(node.superclass, MessageKind.TYPE_NAME_EXPECTED);
     }
     final objectElement = compiler.objectClass;
     if (!identical(element, objectElement) && element.supertype == null) {
@@ -2636,14 +2699,21 @@
     for (Link<Node> link = node.interfaces.nodes;
          !link.isEmpty;
          link = link.tail) {
-      DartType interfaceType = visit(link.head);
-      if (interfaceType != null && interfaceType.element.isExtendable()) {
-        interfaces = interfaces.prepend(interfaceType);
-        if (isBlackListed(interfaceType)) {
-          error(link.head, MessageKind.CANNOT_IMPLEMENT, [interfaceType]);
+      DartType interfaceType = typeResolver.resolveTypeAnnotation(
+          link.head, scope, element, onFailure: error);
+      if (interfaceType != null) {
+        if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) {
+          // Error has already been reported.
+        } else if (!identical(interfaceType.kind, TypeKind.INTERFACE)) {
+          // TODO(johnniwinther): Handle dynamic.
+          TypeAnnotation typeAnnotation = link.head;
+          error(typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
+        } else {
+          interfaces = interfaces.prepend(interfaceType);
+          if (isBlackListed(interfaceType)) {
+            error(link.head, MessageKind.CANNOT_IMPLEMENT, [interfaceType]);
+          }
         }
-      } else {
-        error(link.head, MessageKind.TYPE_NAME_EXPECTED);
       }
     }
     element.interfaces = interfaces;
@@ -2656,10 +2726,12 @@
     return element.computeType(compiler);
   }
 
+  // TODO(johnniwinther): Remove when default class is no longer supported.
   DartType visitTypeAnnotation(TypeAnnotation node) {
     return visit(node.typeName);
   }
 
+  // TODO(johnniwinther): Remove when default class is no longer supported.
   DartType visitIdentifier(Identifier node) {
     Element element = scope.lookup(node.source);
     if (element == null) {
@@ -2682,6 +2754,7 @@
     return null;
   }
 
+  // TODO(johnniwinther): Remove when default class is no longer supported.
   DartType visitSend(Send node) {
     Identifier prefix = node.receiver.asIdentifier();
     if (prefix == null) {
@@ -2704,30 +2777,43 @@
   }
 
   void calculateAllSupertypes(ClassElement cls) {
-    // TODO(karlklose): substitute type variables.
     // TODO(karlklose): check if type arguments match, if a classelement occurs
     //                  more than once in the supertypes.
     if (cls.allSupertypes != null) return;
     final DartType supertype = cls.supertype;
     if (supertype != null) {
-      ClassElement superElement = supertype.element;
-      Link<DartType> superSupertypes = superElement.allSupertypes;
-      assert(superSupertypes != null);
-      Link<DartType> supertypes = superSupertypes.prepend(supertype);
+      var allSupertypes = new LinkBuilder<DartType>();
+      addAllSupertypes(allSupertypes, supertype);
       for (Link<DartType> interfaces = cls.interfaces;
            !interfaces.isEmpty;
            interfaces = interfaces.tail) {
-        ClassElement element = interfaces.head.element;
-        Link<DartType> interfaceSupertypes = element.allSupertypes;
-        assert(interfaceSupertypes != null);
-        supertypes = supertypes.reversePrependAll(interfaceSupertypes);
-        supertypes = supertypes.prepend(interfaces.head);
+        addAllSupertypes(allSupertypes, interfaces.head);
       }
-      cls.allSupertypes = supertypes;
+      cls.allSupertypes = allSupertypes.toLink();
     } else {
       assert(identical(cls, compiler.objectClass));
       cls.allSupertypes = const Link<DartType>();
     }
+ }
+
+  /**
+   * Adds [type] and all supertypes of [type] to [builder] while substituting
+   * type variables.
+   */
+  void addAllSupertypes(LinkBuilder<DartType> builder, InterfaceType type) {
+    builder.addLast(type);
+    Link<DartType> typeArguments = type.typeArguments;
+    ClassElement classElement = type.element;
+    Link<DartType> typeVariables = classElement.typeVariables;
+    Link<DartType> supertypes = classElement.allSupertypes;
+    assert(invariant(element, supertypes != null,
+        message: "Supertypes not computed on $classElement "
+                 "during resolution of $element"));
+    while (!supertypes.isEmpty) {
+      DartType supertype = supertypes.head;
+      builder.addLast(supertype.subst(typeArguments, typeVariables));
+      supertypes = supertypes.tail;
+    }
   }
 
   /**
@@ -2811,7 +2897,7 @@
       } else {
         compiler.reportMessage(
           compiler.spanFromNode(node),
-          MessageKind.TYPE_NAME_EXPECTED.error([]),
+          MessageKind.CLASS_NAME_EXPECTED.error([]),
           Diagnostic.ERROR);
       }
     }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
index ea84f75..01f8e9e 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
@@ -179,6 +179,5 @@
     }
   }
 
-  // TODO(ahe): make class abstract instead of adding an abstract method.
-  peek();
+  void unmatchedBeginGroup(BeginGroupToken begin);
 }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart
index e7ceaf8..fc5e4df 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/class_element_parser.dart
@@ -105,6 +105,9 @@
         listener.cancel('library prefix in named factory constructor not '
                         'implemented', node: send.receiver);
       }
+      if (receiver.source != enclosingElement.name) {
+        listener.onDeprecatedFeature(receiver, 'interface factories');
+      }
       return Elements.constructConstructorName(receiver.source,
                                                selector.source);
     }
@@ -137,6 +140,12 @@
     FunctionExpression method = popNode();
     pushNode(null);
     SourceString name = getMethodNameHack(method.name);
+    Identifier singleIdentifierName = method.name.asIdentifier();
+    if (singleIdentifierName != null && singleIdentifierName.source == name) {
+      if (name != enclosingElement.name) {
+        listener.onDeprecatedFeature(method.name, 'interface factories');
+      }
+    }
     ElementKind kind = ElementKind.FUNCTION;
     Element memberElement =
         new PartialFunctionElement(name, beginToken, null, endToken,
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
index 687cec8..b557d93 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -1337,8 +1337,14 @@
     Node receiver = popNode();
     String tokenString = token.stringValue;
     if (identical(tokenString, '.') || identical(tokenString, '..')) {
-      if (argument is !Send) internalError(node: argument);
-      if (argument.asSend().receiver != null) internalError(node: argument);
+      Send argumentSend = argument.asSend();
+      if (argumentSend == null) {
+        // TODO(ahe): The parser should diagnose this problem, not
+        // this listener.
+        listener.cancel('Syntax error: Expected an identifier.',
+                        node: argument);
+      }
+      if (argumentSend.receiver != null) internalError(node: argument);
       if (argument is SendSet) internalError(node: argument);
       pushNode(argument.asSend().copyWithReceiver(receiver));
     } else {
@@ -1369,8 +1375,9 @@
     Node arg = popNode();
     Node node = popNode();
     Send send = node.asSend();
-    if (send == null) internalError(node: node);
-    if (!(send.isPropertyAccess || send.isIndex)) internalError(node: send);
+    if (send == null || !(send.isPropertyAccess || send.isIndex)) {
+      reportNotAssignable(node);
+    }
     if (send.asSendSet() != null) internalError(node: send);
     NodeList arguments;
     if (send.isIndex) {
@@ -1384,6 +1391,12 @@
     pushNode(new SendSet(send.receiver, send.selector, op, arguments));
   }
 
+  void reportNotAssignable(Node node) {
+    // TODO(ahe): The parser should diagnose this problem, not this
+    // listener.
+    listener.cancel('Syntax error: Not assignable.', node: node);
+  }
+
   void handleConditionalExpression(Token question, Token colon) {
     Node elseExpression = popNode();
     Node thenExpression = popNode();
@@ -1505,8 +1518,12 @@
   void handleUnaryAssignmentExpression(Token token, bool isPrefix) {
     Node node = popNode();
     Send send = node.asSend();
-    if (send == null) internalError(node: node);
-    if (!(send.isPropertyAccess || send.isIndex)) internalError(node: send);
+    if (send == null) {
+      reportNotAssignable(node);
+    }
+    if (!(send.isPropertyAccess || send.isIndex)) {
+      reportNotAssignable(node);
+    }
     if (send.asSendSet() != null) internalError(node: send);
     Node argument = null;
     if (send.isIndex) argument = send.arguments.head;
@@ -1817,8 +1834,8 @@
 
   void internalError({Token token, Node node}) {
     // TODO(ahe): This should call listener.internalError.
-    listener.cancel('internal error', token: token, node: node);
-    throw 'internal error';
+    Spannable spannable = (token == null) ? node : token;
+    throw new SpannableAssertionFailure(spannable, 'internal error in parser');
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
index 498c9fb..a2cd6fc 100644
--- a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
@@ -66,18 +66,22 @@
   }
 
   String build(SourceFile targetFile) {
+    StringBuffer mappingsBuffer = new StringBuffer();
+    entries.forEach((SourceMapEntry entry) => writeEntry(entry, targetFile,
+                                                         mappingsBuffer));
     StringBuffer buffer = new StringBuffer();
     buffer.add('{\n');
     buffer.add('  "version": 3,\n');
-    buffer.add('  "mappings": "');
-    entries.forEach((SourceMapEntry entry) => writeEntry(entry, targetFile, buffer));
-    buffer.add('",\n');
+    buffer.add('  "sourceRoot": "",\n');
     buffer.add('  "sources": ');
     printStringListOn(sourceUrlList, buffer);
     buffer.add(',\n');
     buffer.add('  "names": ');
     printStringListOn(sourceNameList, buffer);
-    buffer.add('\n}\n');
+    buffer.add(',\n');
+    buffer.add('  "mappings": "');
+    buffer.add(mappingsBuffer);
+    buffer.add('"\n}\n');
     return buffer.toString();
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index fcbc105..ebbec8c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -1054,10 +1054,7 @@
     if (node.hasEmptyBody()) return null;
     ClassElement classElement = constructor.getEnclosingClass();
     ConstructorBodyElement bodyElement;
-    for (Link<Element> backendMembers = classElement.backendMembers;
-         !backendMembers.isEmpty;
-         backendMembers = backendMembers.tail) {
-      Element backendMember = backendMembers.head;
+    for (Element backendMember in classElement.backendMembers) {
       if (backendMember.isGenerativeConstructorBody()) {
         ConstructorBodyElement body = backendMember;
         if (body.constructor == constructor) {
@@ -2633,6 +2630,15 @@
     push(result);
   }
 
+  void pushInvokeHelper5(Element helper, HInstruction a0, HInstruction a1,
+                         HInstruction a2, HInstruction a3, HInstruction a4) {
+    HInstruction reference = new HStatic(helper);
+    add(reference);
+    List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3, a4];
+    HInstruction result = new HInvokeStatic(inputs);
+    push(result);
+  }
+
   HForeign createForeign(String code, String type, List<HInstruction> inputs) {
     return new HForeign(new LiteralDartString(code),
                         new LiteralDartString(type),
@@ -2740,8 +2746,8 @@
       }
 
       HInstruction instruction;
-      if (RuntimeTypeInformation.hasTypeArguments(type) ||
-          type.element.isTypeVariable()) {
+      if (type.element.isTypeVariable() ||
+          RuntimeTypeInformation.hasTypeArguments(type)) {
         HInstruction typeInfo = getRuntimeTypeInfo(expression);
         // TODO(karlklose): make isSubtype a HInstruction to enable
         // optimizations?
@@ -3021,7 +3027,7 @@
       // Call a helper method from the isolate library. The isolate
       // library uses its own isolate structure, that encapsulates
       // Leg's isolate.
-      Element element = compiler.isolateLibrary.find(
+      Element element = compiler.isolateHelperLibrary.find(
           const SourceString('_currentIsolate'));
       if (element == null) {
         compiler.cancel(
@@ -3041,7 +3047,7 @@
       push(new HInvokeClosure(selector, <HInstruction>[pop()]));
     } else {
       // Call a helper method from the isolate library.
-      Element element = compiler.isolateLibrary.find(
+      Element element = compiler.isolateHelperLibrary.find(
           const SourceString('_callInIsolate'));
       if (element == null) {
         compiler.cancel(
@@ -3108,21 +3114,58 @@
   }
 
   generateSuperNoSuchMethodSend(Send node) {
+    Selector selector = elements.getSelector(node);
+    SourceString name = selector.name;
+
     ClassElement cls = work.element.getEnclosingClass();
     Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD);
+    if (element.enclosingElement.declaration != compiler.objectClass) {
+      // Register the call as dynamic if [:noSuchMethod:] on the super class
+      // is _not_ the default implementation from [:Object:].
+      compiler.enqueuer.codegen.registerDynamicInvocation(name, selector);
+    }
     HStatic target = new HStatic(element);
     add(target);
     HInstruction self = localsHandler.readThis();
-    Identifier identifier = node.selector.asIdentifier();
-    String name = identifier.source.slowToString();
-    // TODO(ahe): Add the arguments to this list.
-    push(new HLiteralList([]));
-    Constant nameConstant =
-        constantSystem.createString(new DartString.literal(name), node);
+    Constant nameConstant = constantSystem.createString(
+        new DartString.literal(name.slowToString()), node);
+
+    String internalName = backend.namer.instanceMethodInvocationName(
+        currentLibrary, name, selector);
+    Constant internalNameConstant =
+        constantSystem.createString(new DartString.literal(internalName), node);
+
+    Element createInvocationMirror =
+        compiler.findHelper(Compiler.CREATE_INVOCATION_MIRROR);
+
+    var arguments = new List<HInstruction>();
+    addGenericSendArgumentsToList(node.arguments, arguments);
+    var argumentsInstruction = new HLiteralList(arguments);
+    add(argumentsInstruction);
+
+    var argumentNames = new List<HInstruction>();
+    for (SourceString argumentName in selector.namedArguments) {
+      Constant argumentNameConstant =
+          constantSystem.createString(new DartString.literal(
+              argumentName.slowToString()), node);
+      argumentNames.add(graph.addConstant(argumentNameConstant));
+    }
+    var argumentNamesInstruction = new HLiteralList(argumentNames);
+    add(argumentNamesInstruction);
+
+    Constant kindConstant =
+        constantSystem.createInt(selector.invocationMirrorKind);
+
+    pushInvokeHelper5(createInvocationMirror,
+                      graph.addConstant(nameConstant),
+                      graph.addConstant(internalNameConstant),
+                      graph.addConstant(kindConstant),
+                      argumentsInstruction,
+                      argumentNamesInstruction);
+
     var inputs = <HInstruction>[
         target,
         self,
-        graph.addConstant(nameConstant),
         pop()];
     push(new HInvokeSuper(inputs));
   }
@@ -3370,8 +3413,6 @@
         return;
       }
 
-      // TODO(kasperl): Try to use the general inlining infrastructure for
-      // inlining the identical function.
       if (identical(element, compiler.identicalFunction)) {
         pushWithPosition(new HIdentity(target, inputs[1], inputs[2]), node);
         return;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 6beaa0c..bf500a8 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1764,8 +1764,8 @@
         node);
   }
 
-  String _fieldPropertyName(Element element) => element.isNative()
-      ? element.nativeName()
+  String _fieldPropertyName(Element element) => element.hasFixedBackendName()
+      ? element.fixedBackendName()
       : backend.namer.getName(element);
 
   visitLocalGet(HLocalGet node) {
@@ -1777,13 +1777,17 @@
     assignVariable(variableNames.getName(node.receiver), pop());
   }
 
+  // TODO(sra): We could be more picky about when to inhibit renaming of locals
+  // - most JS strings don't contain free variables, or contain safe ones like
+  // 'Object'.  JS strings like "#.length" and "#[#]" are perfectly safe for
+  // variable renaming.  For now, be shy of any potential identifiers.
+  static final RegExp safeCodeRegExp = new RegExp(r'^[^_$a-zA-Z]*$');
+
   visitForeign(HForeign node) {
-    // TODO(sra): We could be a lot more picky about when to inhibit renaming of
-    // locals - most JS strings don't contain free variables, or contain safe
-    // ones like 'Object'.  JS strings like "#.length" and "#[#]" are perfectly
-    // safe for variable renaming.
-    inhibitVariableMinification = true;
     String code = node.code.slowToString();
+    if (!safeCodeRegExp.hasMatch(code)) {
+      inhibitVariableMinification = true;
+    }
     List<HInstruction> inputs = node.inputs;
     if (node.isJsStatement(types)) {
       if (!inputs.isEmpty) {
@@ -1841,6 +1845,10 @@
     assert(isGenerateAtUseSite(node));
     generateConstant(node.constant);
     DartType type = node.constant.computeType(compiler);
+    if (node.constant is ConstructedConstant) {
+      ConstantHandler handler = compiler.constantHandler;
+      handler.registerCompileTimeConstant(node.constant);
+    }
     world.registerInstantiatedClass(type.element);
   }
 
@@ -2347,15 +2355,13 @@
     if (identical(element.kind, ElementKind.TYPE_VARIABLE)) {
       compiler.unimplemented("visitIs for type variables",
                              instruction: node.expression);
-    } else if (identical(element.kind, ElementKind.TYPEDEF)) {
-      compiler.unimplemented("visitIs for typedefs",
-                             instruction: node.expression);
     }
     LibraryElement coreLibrary = compiler.coreLibrary;
     ClassElement objectClass = compiler.objectClass;
     HInstruction input = node.expression;
 
-    if (identical(element, objectClass) || identical(element, compiler.dynamicClass)) {
+    if (identical(element, objectClass) ||
+        identical(element, compiler.dynamicClass)) {
       // The constant folder also does this optimization, but we make
       // it safe by assuming it may have not run.
       push(newLiteralBool(true), node);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 88718e1..290a357 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -2541,7 +2541,7 @@
   HInstruction getCheck(int index) => inputs[index + 1];
   int get checkCount => inputs.length - 1;
 
-  bool hasArgumentChecks() => inputs.length >= 1;
+  bool hasArgumentChecks() => inputs.length > 1;
 
   HType get guaranteedType => HType.BOOLEAN;
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 036d1ac..b6ea705 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -207,7 +207,7 @@
   }
 
   HInstruction handleInterceptorCall(HInvokeDynamic node) {
-    if (node is !HInvokeDynamicMethod) return;
+    if (node is !HInvokeDynamicMethod) return null;
     HInstruction input = node.inputs[1];
     if (input.isString(types)
         && node.selector.name == const SourceString('toString')) {
@@ -511,8 +511,10 @@
   HInstruction visitIs(HIs node) {
     DartType type = node.typeExpression;
     Element element = type.element;
-    if (identical(element.kind, ElementKind.TYPE_VARIABLE)) {
+    if (element.isTypeVariable()) {
       compiler.unimplemented("visitIs for type variables");
+    } if (element.isTypedef()) {
+      return node;
     }
 
     HType expressionType = types[node.expression];
@@ -741,10 +743,8 @@
 
     if (constantInterceptor == null) return node;
 
-    ConstantHandler handler = compiler.constantHandler;
     Constant constant = new ConstructedConstant(
         constantInterceptor.computeType(compiler), <Constant>[]);
-    handler.registerCompileTimeConstant(constant);
     return graph.addConstant(constant);
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/universe/partial_type_tree.dart b/sdk/lib/_internal/compiler/implementation/universe/partial_type_tree.dart
index 0ffbdde..f310174 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/partial_type_tree.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/partial_type_tree.dart
@@ -117,9 +117,9 @@
       // Create a new node and move the children of the current node
       // that are subtypes of the type of the new node below the new
       // node in the hierarchy.
-      PartialTypeTreeNode newNode = newNode(type);
+      PartialTypeTreeNode node = newNode(type);
       if (!subtypes.isEmpty) {
-        newNode.children = subtypes;
+        node.children = subtypes;
         Link<PartialTypeTreeNode> remaining = const Link();
         for (Link link = current.children; !link.isEmpty; link = link.tail) {
           PartialTypeTreeNode child = link.head;
@@ -131,8 +131,8 @@
       }
 
       // Add the new node as a child node of the current node and return it.
-      current.children = current.children.prepend(newNode);
-      return newNode;
+      current.children = current.children.prepend(node);
+      return node;
     }
 
     // We found an exact match. No need to insert new nodes.
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index eff874c..446d835 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -217,6 +217,25 @@
   int get positionalArgumentCount => argumentCount - namedArgumentCount;
   DartType get receiverType => null;
 
+  /**
+   * The member name for invocation mirrors created from this selector.
+   */
+  String get invocationMirrorMemberName =>
+      isSetter() ? '${name.slowToString()}=' : name.slowToString();
+
+  int get invocationMirrorKind {
+    const int METHOD = 0;
+    const int GETTER = 1;
+    const int SETTER = 2;
+    int kind = METHOD;
+    if (isGetter()) {
+      kind = GETTER;
+    } else if (isSetter()) {
+      kind = SETTER;
+    }
+    return kind;
+  }
+
   bool applies(Element element, Compiler compiler)
       => appliesUntyped(element, compiler);
 
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 9c07fd3..5f5b74e 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -187,8 +187,12 @@
 
   static const CYCLIC_TYPE_VARIABLE = const MessageKind(
       "cyclic reference to type variable #{1}");
-  static const TYPE_NAME_EXPECTED = const MessageKind(
-      "class or interface name expected");
+
+  static const CLASS_NAME_EXPECTED = const MessageKind(
+      "class name expected");
+
+  static const INTERFACE_TYPE_EXPECTED = const MessageKind(
+      "interface type expected");
 
   static const CANNOT_EXTEND = const MessageKind(
       "#{1} cannot be extended");
@@ -293,6 +297,9 @@
   static const LIBRARY_NAME_MISMATCH = const MessageKind(
       'Warning: expected part of library name "#{1}".');
 
+  static const MISSING_PART_OF_TAG = const MessageKind(
+      'Note: This file has no part-of tag, but it is being used as a part.');
+
   static const DUPLICATED_PART_OF = const MessageKind(
       'Error: duplicated part-of directive.');
 
diff --git a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
index 1b45e3c..f289ed3 100755
--- a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
@@ -36,7 +36,8 @@
   final argParser = new ArgParser();
 
   final Path libPath = scriptDir.append('../../../../');
-  Path pkgPath = scriptDir.append('../../../../pkg/');
+  
+  Path pkgPath;
 
   argParser.addFlag('no-code',
       help: 'Do not include source code in the documentation.',
@@ -178,8 +179,21 @@
   final entrypoints = <Path>[];
   try {
     final option = argParser.parse(args);
+    
+    // This checks to see if the root of all entrypoints is the same.
+    // If it is not, then we display a warning, as package imports might fail.
+    var entrypointRoot;
     for(final arg in option.rest) {
-      entrypoints.add(new Path.fromNative(arg));
+      var entrypoint = new Path.fromNative(arg);
+      entrypoints.add(entrypoint);
+      
+      if (entrypointRoot == null) {
+        entrypointRoot = entrypoint.directoryPath;
+      } else if (entrypointRoot.toNativePath() !=
+          entrypoint.directoryPath.toNativePath()) {
+        print('Warning: entrypoints are at different directories. "package:"'
+            ' imports may fail.');
+      }
     }
   } on FormatException catch (e) {
     print(e.message);
@@ -193,6 +207,10 @@
     print(argParser.getUsage());
     return;
   }
+  
+  if (pkgPath == null) {
+    pkgPath = entrypoints[0].directoryPath.append('packages/');
+  }
 
   cleanOutputDirectory(dartdoc.outputDir);
 
diff --git a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
index ec86fd3..44c7d69 100644
--- a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
@@ -712,7 +712,7 @@
   /** Writes a linked navigation list item for the given type. */
   void docTypeNavigation(ClassMirror type) {
     var icon = 'interface';
-    if (type.simpleName.endsWith('Exception')) {
+    if (isException(type)) {
       icon = 'exception';
     } else if (type.isClass) {
       icon = 'class';
@@ -874,7 +874,7 @@
    */
   void typeSpan(ClassMirror type) {
     var icon = 'interface';
-    if (type.simpleName.endsWith('Exception')) {
+    if (isException(type)) {
       icon = 'exception';
     } else if (type.isClass) {
       icon = 'class';
diff --git a/sdk/lib/_internal/dartdoc/lib/src/client/client-live-nav.dart b/sdk/lib/_internal/dartdoc/lib/src/client/client-live-nav.dart
index 4405bab..9be17a3 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/client/client-live-nav.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/client/client-live-nav.dart
@@ -66,7 +66,8 @@
   final exceptions = [];
 
   for (Map typeInfo in libraryInfo[TYPES]) {
-    if (typeInfo[NAME].endsWith('Exception')) {
+    var name = typeInfo[NAME];
+    if (name.endsWith('Exception') || name.endsWith('Error')) {
       exceptions.add(typeInfo);
     } else {
       types.add(typeInfo);
diff --git a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
index 143332b..b58195b 100644
--- a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
@@ -5,6 +5,8 @@
 /// Unit tests for doc.
 library dartdocTests;
 
+import 'dart:io';
+
 // TODO(rnystrom): Use "package:" URL (#4968).
 import '../lib/dartdoc.dart' as dd;
 import '../lib/markdown.dart' as md;
@@ -116,4 +118,35 @@
           '../../other/file.html'));
     });
   });
+  
+  group('integration tests', () {
+    test('no entrypoints', () {
+      expect(_runDartdoc([]), completes);
+    });
+
+    test('library with no packages', () {
+      expect(_runDartdoc(
+          [new Path.fromNative('test/test_files/other_place/'
+              'no_package_test_file.dart').toNativePath()]),
+        completes);
+    });
+
+    test('library with packages', () {
+      expect(_runDartdoc(
+          [new Path.fromNative('test/test_files/'
+              'package_test_file.dart').toNativePath()]),
+        completes);
+    });
+
+  });
+}
+
+Future _runDartdoc(List<String> arguments) {
+  var dartBin = new Options().executable;
+  var dartdoc = 'bin/dartdoc.dart';
+  arguments.insertRange(0, 1, dartdoc);
+  return Process.run(dartBin, arguments)
+      .transform((result) {
+        expect(result.exitCode, 0);
+      });
 }
diff --git a/sdk/lib/_internal/dartdoc/test/test_files/other_place/no_package_test_file.dart b/sdk/lib/_internal/dartdoc/test/test_files/other_place/no_package_test_file.dart
new file mode 100644
index 0000000..da52a19
--- /dev/null
+++ b/sdk/lib/_internal/dartdoc/test/test_files/other_place/no_package_test_file.dart
@@ -0,0 +1,5 @@
+library no_package_test;
+
+class NoPackageTestFile {
+  
+}
diff --git a/sdk/lib/_internal/dartdoc/test/test_files/package_test_file.dart b/sdk/lib/_internal/dartdoc/test/test_files/package_test_file.dart
new file mode 100644
index 0000000..de09194
--- /dev/null
+++ b/sdk/lib/_internal/dartdoc/test/test_files/package_test_file.dart
@@ -0,0 +1,5 @@
+library package_test;
+
+class PackageTestFile {
+  
+}
diff --git a/sdk/lib/_internal/dartdoc/test/test_files/packages/fake_package/fake_package.dart b/sdk/lib/_internal/dartdoc/test/test_files/packages/fake_package/fake_package.dart
new file mode 100644
index 0000000..0025791
--- /dev/null
+++ b/sdk/lib/_internal/dartdoc/test/test_files/packages/fake_package/fake_package.dart
@@ -0,0 +1,4 @@
+library fake_package;
+class FakePackage {
+
+}
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index fd8b5ab..29b3f36 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -115,6 +115,12 @@
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
+
+  "_isolate_helper": const LibraryInfo(
+      "_internal/compiler/implementation/lib/isolate_helper.dart",
+      category: "Internal",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
 };
 
 /**
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index eeb0c04..c18e174 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -245,3 +245,12 @@
   const StackOverflowError();
   String toString() => "Stack Overflow";
 }
+
+/**
+ * Error thrown when a runtime error occurs.
+ */
+class RuntimeError implements Error {
+  final message;
+  RuntimeError(this.message);
+  String toString() => "RuntimeError: $message";
+}
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index afe3285..1a7c436 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.dart
@@ -64,12 +64,3 @@
   const IntegerDivisionByZeroException();
   String toString() => "IntegerDivisionByZeroException";
 }
-
-/**
- * Exception thrown when a runtime error occurs.
- */
-class RuntimeError implements Exception {
-  final message;
-  RuntimeError(this.message);
-  String toString() => "RuntimeError: $message";
-}
diff --git a/sdk/lib/core/identical.dart b/sdk/lib/core/identical.dart
index 5de366f..5e8f782 100644
--- a/sdk/lib/core/identical.dart
+++ b/sdk/lib/core/identical.dart
@@ -5,4 +5,4 @@
 /**
  * Check whether two references are to the same object.
  */
-bool identical(Object a, Object b) => a === b;
+external bool identical(Object a, Object b);
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index d0de13d..fb99370 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -73,9 +73,12 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class AbstractWorkerEvents extends Events {
+  /// @docsEditable true
   AbstractWorkerEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -84,7 +87,7 @@
 
 
 /// @domName HTMLAnchorElement; @docsEditable true
-class AnchorElement extends Element implements Element native "*HTMLAnchorElement" {
+class AnchorElement extends Element native "*HTMLAnchorElement" {
 
   ///@docsEditable true
   factory AnchorElement({String href}) {
@@ -229,7 +232,7 @@
 
 
 /// @domName HTMLAppletElement; @docsEditable true
-class AppletElement extends Element implements Element native "*HTMLAppletElement" {
+class AppletElement extends Element native "*HTMLAppletElement" {
 
   /// @domName HTMLAppletElement.align; @docsEditable true
   String align;
@@ -313,23 +316,33 @@
   void update() native;
 }
 
+/// @docsEditable true
 class ApplicationCacheEvents extends Events {
+  /// @docsEditable true
   ApplicationCacheEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get cached => this['cached'];
 
+  /// @docsEditable true
   EventListenerList get checking => this['checking'];
 
+  /// @docsEditable true
   EventListenerList get downloading => this['downloading'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get noUpdate => this['noupdate'];
 
+  /// @docsEditable true
   EventListenerList get obsolete => this['obsolete'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get updateReady => this['updateready'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -338,7 +351,7 @@
 
 
 /// @domName HTMLAreaElement; @docsEditable true
-class AreaElement extends Element implements Element native "*HTMLAreaElement" {
+class AreaElement extends Element native "*HTMLAreaElement" {
 
   ///@docsEditable true
   factory AreaElement() => document.$dom_createElement("area");
@@ -464,7 +477,7 @@
 
 
 /// @domName HTMLBRElement; @docsEditable true
-class BRElement extends Element implements Element native "*HTMLBRElement" {
+class BRElement extends Element native "*HTMLBRElement" {
 
   ///@docsEditable true
   factory BRElement() => document.$dom_createElement("br");
@@ -489,7 +502,7 @@
 
 
 /// @domName HTMLBaseElement; @docsEditable true
-class BaseElement extends Element implements Element native "*HTMLBaseElement" {
+class BaseElement extends Element native "*HTMLBaseElement" {
 
   ///@docsEditable true
   factory BaseElement() => document.$dom_createElement("base");
@@ -506,7 +519,7 @@
 
 
 /// @domName HTMLBaseFontElement; @docsEditable true
-class BaseFontElement extends Element implements Element native "*HTMLBaseFontElement" {
+class BaseFontElement extends Element native "*HTMLBaseFontElement" {
 
   /// @domName HTMLBaseFontElement.color; @docsEditable true
   String color;
@@ -554,15 +567,21 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class BatteryManagerEvents extends Events {
+  /// @docsEditable true
   BatteryManagerEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get chargingChange => this['chargingchange'];
 
+  /// @docsEditable true
   EventListenerList get chargingTimeChange => this['chargingtimechange'];
 
+  /// @docsEditable true
   EventListenerList get dischargingTimeChange => this['dischargingtimechange'];
 
+  /// @docsEditable true
   EventListenerList get levelChange => this['levelchange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -610,7 +629,7 @@
 
 
 /// @domName HTMLBodyElement; @docsEditable true
-class BodyElement extends Element implements Element native "*HTMLBodyElement" {
+class BodyElement extends Element native "*HTMLBodyElement" {
 
   ///@docsEditable true
   factory BodyElement() => document.$dom_createElement("body");
@@ -635,33 +654,48 @@
   String vLink;
 }
 
+/// @docsEditable true
 class BodyElementEvents extends ElementEvents {
+  /// @docsEditable true
   BodyElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get beforeUnload => this['beforeunload'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get hashChange => this['hashchange'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get offline => this['offline'];
 
+  /// @docsEditable true
   EventListenerList get online => this['online'];
 
+  /// @docsEditable true
   EventListenerList get popState => this['popstate'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get storage => this['storage'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -670,7 +704,7 @@
 
 
 /// @domName HTMLButtonElement; @docsEditable true
-class ButtonElement extends Element implements Element native "*HTMLButtonElement" {
+class ButtonElement extends Element native "*HTMLButtonElement" {
 
   ///@docsEditable true
   factory ButtonElement() => document.$dom_createElement("button");
@@ -741,7 +775,7 @@
 
 
 /// @domName HTMLCanvasElement
-class CanvasElement extends Element implements Element native "*HTMLCanvasElement" {
+class CanvasElement extends Element native "*HTMLCanvasElement" {
 
   ///@docsEditable true
   factory CanvasElement({int width, int height}) {
@@ -751,12 +785,54 @@
     return e;
   }
 
+  /// The height of this canvas element in CSS pixels.
   /// @domName HTMLCanvasElement.height; @docsEditable true
   int height;
 
+  /// The width of this canvas element in CSS pixels.
   /// @domName HTMLCanvasElement.width; @docsEditable true
   int width;
 
+  /**
+   * Returns a data URI containing a representation of the image in the 
+   * format specified by type (defaults to 'image/png'). 
+   * 
+   * Data Uri format is as follow `data:[<MIME-type>][;charset=<encoding>][;base64],<data>`
+   * 
+   * Optional parameter [quality] in the range of 0.0 and 1.0 can be used when requesting [type]
+   * 'image/jpeg' or 'image/webp'. If [quality] is not passed the default
+   * value is used. Note: the default value varies by browser.
+   * 
+   * If the height or width of this canvas element is 0, then 'data:' is returned,
+   * representing no data.
+   * 
+   * If the type requested is not 'image/png', and the returned value is 
+   * 'data:image/png', then the requested type is not supported.
+   * 
+   * Example usage:
+   * 
+   *     CanvasElement canvas = new CanvasElement();
+   *     var ctx = canvas.context2d
+   *     ..fillStyle = "rgb(200,0,0)"
+   *     ..fillRect(10, 10, 55, 50);
+   *     var dataUrl = canvas.toDataURL("image/jpeg", 0.95);
+   *     // The Data Uri would look similar to
+   *     // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
+   *     // AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
+   *     // 9TXL0Y4OHwAAAABJRU5ErkJggg=='
+   *     //Create a new image element from the data URI.
+   *     var img = new ImageElement();
+   *     img.src = dataUrl;
+   *     document.body.children.add(img);
+   *     
+   * See also:
+   * 
+   * * [Data URI Scheme](http://en.wikipedia.org/wiki/Data_URI_scheme) from Wikipedia.
+   * 
+   * * [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/DOM/HTMLCanvasElement) from MDN.
+   * 
+   * * [toDataUrl](http://dev.w3.org/html5/spec/the-canvas-element.html#dom-canvas-todataurl) from W3C.
+   */
   /// @domName HTMLCanvasElement.toDataURL; @docsEditable true
   @JSName('toDataURL')
   String toDataUrl(String type, [num quality]) native;
@@ -770,9 +846,47 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+/**
+ * An opaque canvas object representing a gradient.
+ *
+ * Created by calling [createLinearGradient] or [createRadialGradient] on a
+ * [CanvasRenderingContext2D] object.
+ *
+ * Example usage:
+ *
+ *     var canvas = new CanvasElement(width: 600, height: 600);
+ *     var ctx = canvas.context2d;
+ *     ctx.clearRect(0, 0, 600, 600);
+ *     ctx.save();
+ *     // Create radial gradient.
+ *     CanvasGradient gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, 600);
+ *     gradient.addColorStop(0, '#000');
+ *     gradient.addColorStop(1, 'rgb(255, 255, 255)');
+ *     // Assign gradients to fill.
+ *     ctx.fillStyle = gradient;
+ *     // Draw a rectangle with a gradient fill.
+ *     ctx.fillRect(0, 0, 600, 600);
+ *     ctx.save();
+ *     document.body.children.add(canvas);
+ *
+ * See also:
+ *
+ * * [CanvasGradient](https://developer.mozilla.org/en-US/docs/DOM/CanvasGradient) from MDN.
+ * * [CanvasGradient](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasgradient) from whatwg.
+ * * [CanvasGradient](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvasgradient) from W3C.
+ */
 /// @domName CanvasGradient; @docsEditable true
 class CanvasGradient native "*CanvasGradient" {
 
+  /**
+   * Adds a color stop to this gradient at the offset.
+   *
+   * The [offset] can range between 0.0 and 1.0.
+   *
+   * See also:
+   *
+   * * [Multiple Color Stops](https://developer.mozilla.org/en-US/docs/CSS/linear-gradient#Gradient_with_multiple_color_stops) from MDN.
+   */
   /// @domName CanvasGradient.addColorStop; @docsEditable true
   void addColorStop(num offset, String color) native;
 }
@@ -781,6 +895,33 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+/**
+ * An opaque object representing a pattern of image, canvas, or video.
+ *
+ * Created by calling [createPattern] on a [CanvasRenderingContext2D] object.
+ *
+ * Example usage:
+ *
+ *     var canvas = new CanvasElement(width: 600, height: 600);
+ *     var ctx = canvas.context2d;
+ *     var img = new ImageElement();
+ *     // Image src needs to be loaded before pattern is applied.
+ *     img.on.load.add((event) {
+ *       // When the image is loaded, create a pattern
+ *       // from the ImageElement.
+ *       CanvasPattern pattern = ctx.createPattern(img, 'repeat');
+ *       ctx.rect(0, 0, canvas.width, canvas.height);
+ *       ctx.fillStyle = pattern;
+ *       ctx.fill();
+ *     });
+ *     img.src = "images/foo.jpg";
+ *     document.body.children.add(canvas);
+ *
+ * See also:
+ * * [CanvasPattern](https://developer.mozilla.org/en-US/docs/DOM/CanvasPattern) from MDN.
+ * * [CanvasPattern](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvaspattern) from whatwg.
+ * * [CanvasPattern](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvaspattern) from W3C.
+ */
 /// @domName CanvasPattern; @docsEditable true
 class CanvasPattern native "*CanvasPattern" {
 }
@@ -789,9 +930,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+/**
+ * A rendering context for a canvas element.
+ *
+ * This context is extended by [CanvasRenderingContext2D] and
+ * [WebGLRenderingContext].
+ */
 /// @domName CanvasRenderingContext; @docsEditable true
 class CanvasRenderingContext native "*CanvasRenderingContext" {
 
+  /// Reference to the canvas element to which this context belongs.
   /// @domName CanvasRenderingContext.canvas; @docsEditable true
   final CanvasElement canvas;
 }
@@ -1336,7 +1484,7 @@
 
 
 /// @domName HTMLContentElement; @docsEditable true
-class ContentElement extends Element implements Element native "*HTMLContentElement" {
+class ContentElement extends Element native "*HTMLContentElement" {
 
   ///@docsEditable true
   factory ContentElement() => document.$dom_createElement("content");
@@ -5142,7 +5290,7 @@
 
 
 /// @domName HTMLDListElement; @docsEditable true
-class DListElement extends Element implements Element native "*HTMLDListElement" {
+class DListElement extends Element native "*HTMLDListElement" {
 
   ///@docsEditable true
   factory DListElement() => document.$dom_createElement("dl");
@@ -5156,7 +5304,7 @@
 
 
 /// @domName HTMLDataListElement; @docsEditable true
-class DataListElement extends Element implements Element native "*HTMLDataListElement" {
+class DataListElement extends Element native "*HTMLDataListElement" {
 
   ///@docsEditable true
   factory DataListElement() => document.$dom_createElement("datalist");
@@ -5354,9 +5502,12 @@
   void _postMessage_2(message) native;
 }
 
+/// @docsEditable true
 class DedicatedWorkerContextEvents extends WorkerContextEvents {
+  /// @docsEditable true
   DedicatedWorkerContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -5365,7 +5516,7 @@
 
 
 /// @domName HTMLDetailsElement; @docsEditable true
-class DetailsElement extends Element implements Element native "*HTMLDetailsElement" {
+class DetailsElement extends Element native "*HTMLDetailsElement" {
 
   ///@docsEditable true
   factory DetailsElement() => document.$dom_createElement("details");
@@ -5413,7 +5564,7 @@
 
 
 /// @domName HTMLDirectoryElement; @docsEditable true
-class DirectoryElement extends Element implements Element native "*HTMLDirectoryElement" {
+class DirectoryElement extends Element native "*HTMLDirectoryElement" {
 
   /// @domName HTMLDirectoryElement.compact; @docsEditable true
   bool compact;
@@ -5548,8 +5699,29 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+/**
+ * Represents an HTML <div> element.
+ *
+ * The [DivElement] is a generic container for content and does not have any
+ * special significance. It is functionally similar to [SpanElement].
+ *
+ * The [DivElement] is a block-level element, as opposed to [SpanElement],
+ * which is an inline-level element.
+ *
+ * Example usage:
+ *
+ *     DivElement div = new DivElement();
+ *     div.text = 'Here's my new DivElem
+ *     document.body.elements.add(elem);
+ *
+ * See also:
+ *
+ * * [HTML <div> element](http://www.w3.org/TR/html-markup/div.html) from W3C.
+ * * [Block-level element](http://www.w3.org/TR/CSS2/visuren.html#block-boxes) from W3C.
+ * * [Inline-level element](http://www.w3.org/TR/CSS2/visuren.html#inline-boxes) from W3C.
+ */
 /// @domName HTMLDivElement; @docsEditable true
-class DivElement extends Element implements Element native "*HTMLDivElement" {
+class DivElement extends Element native "*HTMLDivElement" {
 
   ///@docsEditable true
   factory DivElement() => document.$dom_createElement("div");
@@ -5577,6 +5749,7 @@
   DocumentEvents get on =>
     new DocumentEvents(this);
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.body; @docsEditable true
   @JSName('body')
   Element $dom_body;
@@ -5587,6 +5760,7 @@
   /// @domName Document.cookie; @docsEditable true
   String cookie;
 
+  /// Returns the [Window] associated with the document.
   /// @domName Document.defaultView; @docsEditable true
   Window get window => _convertNativeToDart_Window(this._window);
   @JSName('defaultView')
@@ -5599,6 +5773,7 @@
   /// @domName Document.domain; @docsEditable true
   final String domain;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.head; @docsEditable true
   @JSName('head')
   final HeadElement $dom_head;
@@ -5606,6 +5781,7 @@
   /// @domName Document.implementation; @docsEditable true
   final DomImplementation implementation;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.lastModified; @docsEditable true
   @JSName('lastModified')
   final String $dom_lastModified;
@@ -5617,6 +5793,7 @@
   /// @domName Document.readyState; @docsEditable true
   final String readyState;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.referrer; @docsEditable true
   @JSName('referrer')
   final String $dom_referrer;
@@ -5625,39 +5802,48 @@
   @JSName('selectedStylesheetSet')
   String $dom_selectedStylesheetSet;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.styleSheets; @docsEditable true
   @JSName('styleSheets')
   @Returns('_StyleSheetList') @Creates('_StyleSheetList')
   final List<StyleSheet> $dom_styleSheets;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.title; @docsEditable true
   @JSName('title')
   String $dom_title;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitFullscreenElement; @docsEditable true
   @JSName('webkitFullscreenElement')
   final Element $dom_webkitFullscreenElement;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitFullscreenEnabled; @docsEditable true
   @JSName('webkitFullscreenEnabled')
   final bool $dom_webkitFullscreenEnabled;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitHidden; @docsEditable true
   @JSName('webkitHidden')
   final bool $dom_webkitHidden;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitIsFullScreen; @docsEditable true
   @JSName('webkitIsFullScreen')
   final bool $dom_webkitIsFullScreen;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitPointerLockElement; @docsEditable true
   @JSName('webkitPointerLockElement')
   final Element $dom_webkitPointerLockElement;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitVisibilityState; @docsEditable true
   @JSName('webkitVisibilityState')
   final String $dom_webkitVisibilityState;
 
+  /// Use the [Range] constructor instead.
   /// @domName Document.caretRangeFromPoint; @docsEditable true
   @JSName('caretRangeFromPoint')
   Range $dom_caretRangeFromPoint(int x, int y) native;
@@ -5669,6 +5855,7 @@
   /// @domName Document.createDocumentFragment; @docsEditable true
   DocumentFragment createDocumentFragment() native;
 
+  /// Deprecated: use new Element.tag(tagName) instead.
   /// @domName Document.createElement; @docsEditable true
   @JSName('createElement')
   Element $dom_createElement(String tagName) native;
@@ -5697,10 +5884,12 @@
   @JSName('createTouch')
   Touch _$dom_createTouch_1(LocalWindow window, target, identifier, pageX, pageY, screenX, screenY, webkitRadiusX, webkitRadiusY, webkitRotationAngle, webkitForce) native;
 
+  /// Use the [TouchList] constructor isntead.
   /// @domName Document.createTouchList; @docsEditable true
   @JSName('createTouchList')
   TouchList $dom_createTouchList() native;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.elementFromPoint; @docsEditable true
   @JSName('elementFromPoint')
   Element $dom_elementFromPoint(int x, int y) native;
@@ -5712,6 +5901,7 @@
   @JSName('getCSSCanvasContext')
   CanvasRenderingContext $dom_getCssCanvasContext(String contextId, String name, int width, int height) native;
 
+  /// Deprecated: use query("#$elementId") instead.
   /// @domName Document.getElementById; @docsEditable true
   @JSName('getElementById')
   Element $dom_getElementById(String elementId) native;
@@ -5746,23 +5936,28 @@
   /// @domName Document.queryCommandValue; @docsEditable true
   String queryCommandValue(String command) native;
 
+  /// Deprecated: renamed to the shorter name [query].
   /// @domName Document.querySelector; @docsEditable true
   @JSName('querySelector')
   Element $dom_querySelector(String selectors) native;
 
+  /// Deprecated: use query("#$elementId") instead.
   /// @domName Document.querySelectorAll; @docsEditable true
   @JSName('querySelectorAll')
   @Returns('NodeList') @Creates('NodeList')
   List<Node> $dom_querySelectorAll(String selectors) native;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitCancelFullScreen; @docsEditable true
   @JSName('webkitCancelFullScreen')
   void $dom_webkitCancelFullScreen() native;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitExitFullscreen; @docsEditable true
   @JSName('webkitExitFullscreen')
   void $dom_webkitExitFullscreen() native;
 
+  /// Moved to [HtmlDocument].
   /// @domName Document.webkitExitPointerLock; @docsEditable true
   @JSName('webkitExitPointerLock')
   void $dom_webkitExitPointerLock() native;
@@ -5830,15 +6025,21 @@
   }
 }
 
+/// @docsEditable true
 class DocumentEvents extends ElementEvents {
+  /// @docsEditable true
   DocumentEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get readyStateChange => this['readystatechange'];
 
+  /// @docsEditable true
   EventListenerList get selectionChange => this['selectionchange'];
 
+  /// @docsEditable true
   EventListenerList get pointerLockChange => this['webkitpointerlockchange'];
 
+  /// @docsEditable true
   EventListenerList get pointerLockError => this['webkitpointerlockerror'];
 }
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
@@ -5871,9 +6072,11 @@
   factory DocumentFragment.svg(String svgContent) =>
       _DocumentFragmentFactoryProvider.createDocumentFragment_svg(svgContent);
 
+  @deprecated
   List<Element> get elements => this.children;
 
   // TODO: The type of value should be Collection<Element>. See http://b/5392897
+  @deprecated
   void set elements(value) {
     this.children = value;
   }
@@ -5979,12 +6182,12 @@
   String get webkitdropzone => "";
   String get webkitRegionOverflow => "";
   Element get $m_firstElementChild {
-    if (elements.length > 0) {
-      return elements[0];
+    if (children.length > 0) {
+      return children[0];
     }
     return null;
   }
-  Element get $m_lastElementChild => elements.last;
+  Element get $m_lastElementChild => children.last;
   Element get nextElementSibling => null;
   Element get previousElementSibling => null;
   Element get offsetParent => null;
@@ -7173,11 +7376,14 @@
   /**
    * Deprecated, use innerHtml instead.
    */
+  @deprecated
   String get innerHTML => this.innerHtml;
+  @deprecated
   void set innerHTML(String value) {
     this.innerHtml = value;
   }
 
+  @deprecated
   void set elements(Collection<Element> value) {
     this.children = value;
   }
@@ -7185,6 +7391,7 @@
   /**
    * Deprecated, use [children] instead.
    */
+  @deprecated
   List<Element> get elements => this.children;
 
   /**
@@ -7325,7 +7532,7 @@
   void _insertAdjacentNode(String where, Node node) {
     switch (where.toLowerCase()) {
       case 'beforebegin':
-        this.parent.insertBefore(node, this);
+        this.parentNode.insertBefore(node, this);
         break;
       case 'afterbegin':
         var first = this.nodes.length > 0 ? this.nodes[0] : null;
@@ -7335,7 +7542,7 @@
         this.nodes.add(node);
         break;
       case 'afterend':
-        this.parent.insertBefore(node, this.nextNode);
+        this.parentNode.insertBefore(node, this.nextNode);
         break;
       default:
         throw new ArgumentError("Invalid position ${where}");
@@ -7628,98 +7835,145 @@
 class ElementEvents extends Events {
   ElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get beforeCopy => this['beforecopy'];
 
+  /// @docsEditable true
   EventListenerList get beforeCut => this['beforecut'];
 
+  /// @docsEditable true
   EventListenerList get beforePaste => this['beforepaste'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get change => this['change'];
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get contextMenu => this['contextmenu'];
 
+  /// @docsEditable true
   EventListenerList get copy => this['copy'];
 
+  /// @docsEditable true
   EventListenerList get cut => this['cut'];
 
+  /// @docsEditable true
   EventListenerList get doubleClick => this['dblclick'];
 
+  /// @docsEditable true
   EventListenerList get drag => this['drag'];
 
+  /// @docsEditable true
   EventListenerList get dragEnd => this['dragend'];
 
+  /// @docsEditable true
   EventListenerList get dragEnter => this['dragenter'];
 
+  /// @docsEditable true
   EventListenerList get dragLeave => this['dragleave'];
 
+  /// @docsEditable true
   EventListenerList get dragOver => this['dragover'];
 
+  /// @docsEditable true
   EventListenerList get dragStart => this['dragstart'];
 
+  /// @docsEditable true
   EventListenerList get drop => this['drop'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get input => this['input'];
 
+  /// @docsEditable true
   EventListenerList get invalid => this['invalid'];
 
+  /// @docsEditable true
   EventListenerList get keyDown => this['keydown'];
 
+  /// @docsEditable true
   EventListenerList get keyPress => this['keypress'];
 
+  /// @docsEditable true
   EventListenerList get keyUp => this['keyup'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get mouseDown => this['mousedown'];
 
+  /// @docsEditable true
   EventListenerList get mouseMove => this['mousemove'];
 
+  /// @docsEditable true
   EventListenerList get mouseOut => this['mouseout'];
 
+  /// @docsEditable true
   EventListenerList get mouseOver => this['mouseover'];
 
+  /// @docsEditable true
   EventListenerList get mouseUp => this['mouseup'];
 
+  /// @docsEditable true
   EventListenerList get paste => this['paste'];
 
+  /// @docsEditable true
   EventListenerList get reset => this['reset'];
 
+  /// @docsEditable true
   EventListenerList get scroll => this['scroll'];
 
+  /// @docsEditable true
   EventListenerList get search => this['search'];
 
+  /// @docsEditable true
   EventListenerList get select => this['select'];
 
+  /// @docsEditable true
   EventListenerList get selectStart => this['selectstart'];
 
+  /// @docsEditable true
   EventListenerList get submit => this['submit'];
 
+  /// @docsEditable true
   EventListenerList get touchCancel => this['touchcancel'];
 
+  /// @docsEditable true
   EventListenerList get touchEnd => this['touchend'];
 
+  /// @docsEditable true
   EventListenerList get touchEnter => this['touchenter'];
 
+  /// @docsEditable true
   EventListenerList get touchLeave => this['touchleave'];
 
+  /// @docsEditable true
   EventListenerList get touchMove => this['touchmove'];
 
+  /// @docsEditable true
   EventListenerList get touchStart => this['touchstart'];
 
+  /// @docsEditable true
   EventListenerList get transitionEnd => this['webkitTransitionEnd'];
 
+  /// @docsEditable true
   EventListenerList get fullscreenChange => this['webkitfullscreenchange'];
 
+  /// @docsEditable true
   EventListenerList get fullscreenError => this['webkitfullscreenerror'];
 
   EventListenerList get mouseWheel {
@@ -7759,7 +8013,7 @@
 
 
 /// @domName HTMLEmbedElement; @docsEditable true
-class EmbedElement extends Element implements Element native "*HTMLEmbedElement" {
+class EmbedElement extends Element native "*HTMLEmbedElement" {
 
   ///@docsEditable true
   factory EmbedElement() => document.$dom_createElement("embed");
@@ -8093,13 +8347,18 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class EventSourceEvents extends Events {
+  /// @docsEditable true
   EventSourceEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -8213,7 +8472,7 @@
 
 
 /// @domName HTMLFieldSetElement; @docsEditable true
-class FieldSetElement extends Element implements Element native "*HTMLFieldSetElement" {
+class FieldSetElement extends Element native "*HTMLFieldSetElement" {
 
   ///@docsEditable true
   factory FieldSetElement() => document.$dom_createElement("fieldset");
@@ -8554,19 +8813,27 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class FileReaderEvents extends Events {
+  /// @docsEditable true
   FileReaderEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get loadEnd => this['loadend'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -8684,19 +8951,27 @@
   void write(Blob data) native;
 }
 
+/// @docsEditable true
 class FileWriterEvents extends Events {
+  /// @docsEditable true
   FileWriterEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get write => this['write'];
 
+  /// @docsEditable true
   EventListenerList get writeEnd => this['writeend'];
 
+  /// @docsEditable true
   EventListenerList get writeStart => this['writestart'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -8988,7 +9263,7 @@
 
 
 /// @domName HTMLFontElement; @docsEditable true
-class FontElement extends Element implements Element native "*HTMLFontElement" {
+class FontElement extends Element native "*HTMLFontElement" {
 
   /// @domName HTMLFontElement.color; @docsEditable true
   String color;
@@ -9015,8 +9290,8 @@
     return _FormDataFactoryProvider.createFormData(form);
   }
 
-  /// @domName FormData.append; @docsEditable true
-  void append(String name, String value, String filename) native;
+  /// @domName DOMFormData.append; @docsEditable true
+  void append(String name, value, [String filename]) native;
 }
 // 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
@@ -9024,7 +9299,7 @@
 
 
 /// @domName HTMLFormElement; @docsEditable true
-class FormElement extends Element implements Element native "*HTMLFormElement" {
+class FormElement extends Element native "*HTMLFormElement" {
 
   ///@docsEditable true
   factory FormElement() => document.$dom_createElement("form");
@@ -9074,7 +9349,7 @@
 
 
 /// @domName HTMLFrameElement; @docsEditable true
-class FrameElement extends Element implements Element native "*HTMLFrameElement" {
+class FrameElement extends Element native "*HTMLFrameElement" {
 
   /// @domName HTMLFrameElement.contentWindow; @docsEditable true
   Window get contentWindow => _convertNativeToDart_Window(this._contentWindow);
@@ -9121,7 +9396,7 @@
 
 
 /// @domName HTMLFrameSetElement; @docsEditable true
-class FrameSetElement extends Element implements Element native "*HTMLFrameSetElement" {
+class FrameSetElement extends Element native "*HTMLFrameSetElement" {
 
   /// @domName EventTarget.addEventListener, EventTarget.removeEventListener, EventTarget.dispatchEvent; @docsEditable true
   FrameSetElementEvents get on =>
@@ -9134,33 +9409,48 @@
   String rows;
 }
 
+/// @docsEditable true
 class FrameSetElementEvents extends ElementEvents {
+  /// @docsEditable true
   FrameSetElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get beforeUnload => this['beforeunload'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get hashChange => this['hashchange'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get offline => this['offline'];
 
+  /// @docsEditable true
   EventListenerList get online => this['online'];
 
+  /// @docsEditable true
   EventListenerList get popState => this['popstate'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get storage => this['storage'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -9223,7 +9513,7 @@
 
 
 /// @domName HTMLHRElement; @docsEditable true
-class HRElement extends Element implements Element native "*HTMLHRElement" {
+class HRElement extends Element native "*HTMLHRElement" {
 
   ///@docsEditable true
   factory HRElement() => document.$dom_createElement("hr");
@@ -9265,7 +9555,7 @@
 
 
 /// @domName HTMLHeadElement; @docsEditable true
-class HeadElement extends Element implements Element native "*HTMLHeadElement" {
+class HeadElement extends Element native "*HTMLHeadElement" {
 
   ///@docsEditable true
   factory HeadElement() => document.$dom_createElement("head");
@@ -9279,7 +9569,7 @@
 
 
 /// @domName HTMLHeadingElement; @docsEditable true
-class HeadingElement extends Element implements Element native "*HTMLHeadingElement" {
+class HeadingElement extends Element native "*HTMLHeadingElement" {
 
   ///@docsEditable true
   factory HeadingElement.h1() => document.$dom_createElement("h1");
@@ -9646,7 +9936,7 @@
 
 
 /// @domName HTMLHtmlElement; @docsEditable true
-class HtmlElement extends Element implements Element native "*HTMLHtmlElement" {
+class HtmlElement extends Element native "*HTMLHtmlElement" {
 
   ///@docsEditable true
   factory HtmlElement() => document.$dom_createElement("html");
@@ -9731,9 +10021,27 @@
       onComplete);
 
 
+  /**
+   * General constructor for any type of request (GET, POST, etc).
+   *
+   * This call is used in conjunction with [open]:
+   * 
+   *     var request = new HttpRequest();
+   *     request.open('GET', 'http://dartlang.org')
+   *     request.on.load.add((event) => print('Request complete'));
+   * 
+   * is the (more verbose) equivalent of
+   * 
+   *     var request = new HttpRequest.get('http://dartlang.org', (event) => print('Request complete'));
+   */
   ///@docsEditable true
   factory HttpRequest() => _HttpRequestFactoryProvider.createHttpRequest();
 
+  /**
+   * Get the set of [HttpRequestEvents] that this request can respond to.
+   * Usually used when adding an EventListener, such as in
+   * `document.window.on.keyDown.add((e) => print('keydown happened'))`.
+   */
   /// @domName EventTarget.addEventListener, EventTarget.removeEventListener, EventTarget.dispatchEvent; @docsEditable true
   HttpRequestEvents get on =>
     new HttpRequestEvents(this);
@@ -9748,16 +10056,37 @@
 
   static const int UNSENT = 0;
 
+  /** @domName XMLHttpRequest.readyState */
   /// @domName XMLHttpRequest.readyState; @docsEditable true
   final int readyState;
 
+  /**
+   * The data received as a reponse from the request.
+   *
+   * The data could be in the
+   * form of a [String], [ArrayBuffer], [Document], [Blob], or json (also a 
+   * [String]). `null` indicates request failure.
+   */
   /// @domName XMLHttpRequest.response; @docsEditable true
   @Creates('ArrayBuffer|Blob|Document|=Object|=List|String|num')
   final Object response;
 
+  /**
+   * The response in string form or `null` on failure.
+   */
   /// @domName XMLHttpRequest.responseText; @docsEditable true
   final String responseText;
 
+  /**
+   * [String] telling the server the desired response format. 
+   *
+   * Default is `String`.
+   * Other options are one of 'arraybuffer', 'blob', 'document', 'json',
+   * 'text'. Some newer browsers will throw NS_ERROR_DOM_INVALID_ACCESS_ERR if
+   * `responseType` is set while performing a synchronous request.
+   *
+   * See also: [MDN responseType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType)
+   */
   /// @domName XMLHttpRequest.responseType; @docsEditable true
   String responseType;
 
@@ -9765,18 +10094,43 @@
   @JSName('responseXML')
   final Document responseXml;
 
+  /**
+   * The http result code from the request (200, 404, etc).
+   * See also: [Http Status Codes](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
+   */
   /// @domName XMLHttpRequest.status; @docsEditable true
   final int status;
 
+  /**
+   * The request response string (such as "200 OK").
+   * See also: [Http Status Codes](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
+   */
   /// @domName XMLHttpRequest.statusText; @docsEditable true
   final String statusText;
 
+  /**
+   * [EventTarget] that can hold listeners to track the progress of the request.
+   * The events fired will be members of [HttpRequestUploadEvents].
+   */
   /// @domName XMLHttpRequest.upload; @docsEditable true
   final HttpRequestUpload upload;
 
+  /**
+   * True if cross-site requests should use credentials such as cookies
+   * or authorization headers; false otherwise. 
+   *
+   * This value is ignored for same-site requests.
+   */
   /// @domName XMLHttpRequest.withCredentials; @docsEditable true
   bool withCredentials;
 
+  /**
+   * Stop the current request.
+   *
+   * The request can only be stopped if readyState is `HEADERS_RECIEVED` or 
+   * `LOADING`. If this method is not in the process of being sent, the method
+   * has no effect.
+   */
   /// @domName XMLHttpRequest.abort; @docsEditable true
   void abort() native;
 
@@ -9788,15 +10142,48 @@
   @JSName('dispatchEvent')
   bool $dom_dispatchEvent(Event evt) native;
 
+  /**
+   * Retrieve all the response headers from a request.
+   * 
+   * `null` if no headers have been received. For multipart requests,
+   * `getAllResponseHeaders` will return the response headers for the current
+   * part of the request.
+   * 
+   * See also [HTTP response headers](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses)
+   * for a list of common response headers.
+   */
   /// @domName XMLHttpRequest.getAllResponseHeaders; @docsEditable true
   String getAllResponseHeaders() native;
 
+  /**
+   * Return the response header named `header`, or `null` if not found.
+   * 
+   * See also [HTTP response headers](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses)
+   * for a list of common response headers.
+   */
   /// @domName XMLHttpRequest.getResponseHeader; @docsEditable true
   String getResponseHeader(String header) native;
 
+  /**
+   * Specify the desired `url`, and `method` to use in making the request.
+   * 
+   * By default the request is done asyncronously, with no user or password
+   * authentication information. If `async` is false, the request will be send
+   * synchronously.
+   * 
+   * Calling `open` again on a currently active request is equivalent to
+   * calling `abort`.
+   */
   /// @domName XMLHttpRequest.open; @docsEditable true
   void open(String method, String url, [bool async, String user, String password]) native;
 
+  /**
+   * Specify a particular MIME type (such as `text/xml`) desired for the
+   * response.
+   * 
+   * This value must be set before the request has been sent. See also the list
+   * of [common MIME types](http://en.wikipedia.org/wiki/Internet_media_type#List_of_common_media_types)
+   */
   /// @domName XMLHttpRequest.overrideMimeType; @docsEditable true
   void overrideMimeType(String override) native;
 
@@ -9804,29 +10191,90 @@
   @JSName('removeEventListener')
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 
+  /**
+   * Send the request with any given `data`.
+   *
+   * See also: 
+   * [send() docs](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#send())
+   * from MDN.
+   */
   /// @domName XMLHttpRequest.send; @docsEditable true
   void send([data]) native;
 
+  /** Sets HTTP `header` to `value`. */
   /// @domName XMLHttpRequest.setRequestHeader; @docsEditable true
   void setRequestHeader(String header, String value) native;
 
 }
 
+/**
+ * A class that supports listening for and dispatching events that can fire when
+ * making an HTTP request. 
+ *  
+ * Here's an example of adding an event handler that executes once an HTTP
+ * request has fully loaded:
+ * 
+ *     httpRequest.on.loadEnd.add((e) => myCustomLoadEndHandler(e));
+ *
+ * Each property of this class is a read-only pointer to an [EventListenerList].
+ * That list holds all of the [EventListener]s that have registered for that
+ * particular type of event that fires from an HttpRequest.
+ */
+/// @docsEditable true
 class HttpRequestEvents extends Events {
+  /// @docsEditable true
   HttpRequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /**
+   * Event listeners to be notified when request has been aborted,
+   * generally due to calling `httpRequest.abort()`.
+   */
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /**
+   * Event listeners to be notified when a request has failed, such as when a
+   * cross-domain error occurred or the file wasn't found on the server.
+   */
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /**
+   * Event listeners to be notified once the request has completed
+   * *successfully*.
+   */
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /**
+   * Event listeners to be notified once the request has completed (on
+   * either success or failure).
+   */
+  /// @docsEditable true
   EventListenerList get loadEnd => this['loadend'];
 
+  /**
+   * Event listeners to be notified when the request starts, once
+   * `httpRequest.send()` has been called.
+   */
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /**
+   * Event listeners to be notified when data for the request 
+   * is being sent or loaded.
+   *
+   * Progress events are fired every 50ms or for every byte transmitted,
+   * whichever is less frequent.
+   */
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /**
+   * Event listeners to be notified every time the [HttpRequest]
+   * object's `readyState` changes values.
+   */
+  /// @docsEditable true
   EventListenerList get readyStateChange => this['readystatechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -9892,19 +10340,27 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class HttpRequestUploadEvents extends Events {
+  /// @docsEditable true
   HttpRequestUploadEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get loadEnd => this['loadend'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -9913,7 +10369,7 @@
 
 
 /// @domName HTMLIFrameElement; @docsEditable true
-class IFrameElement extends Element implements Element native "*HTMLIFrameElement" {
+class IFrameElement extends Element native "*HTMLIFrameElement" {
 
   ///@docsEditable true
   factory IFrameElement() => document.$dom_createElement("iframe");
@@ -10008,7 +10464,7 @@
 
 
 /// @domName HTMLImageElement; @docsEditable true
-class ImageElement extends Element implements Element native "*HTMLImageElement" {
+class ImageElement extends Element native "*HTMLImageElement" {
 
   ///@docsEditable true
   factory ImageElement({String src, int width, int height}) {
@@ -10081,8 +10537,31 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-/// @domName HTMLInputElement; @docsEditable true
-class InputElement extends Element implements Element native "*HTMLInputElement" {
+/// @domName HTMLInputElement
+class InputElement extends Element implements
+    HiddenInputElement,
+    SearchInputElement,
+    TextInputElement,
+    UrlInputElement,
+    TelephoneInputElement,
+    EmailInputElement,
+    PasswordInputElement,
+    DateTimeInputElement,
+    DateInputElement,
+    MonthInputElement,
+    WeekInputElement,
+    TimeInputElement,
+    LocalDateTimeInputElement,
+    NumberInputElement,
+    RangeInputElement,
+    CheckboxInputElement,
+    RadioButtonInputElement,
+    FileUploadInputElement,
+    SubmitButtonInputElement,
+    ImageButtonInputElement,
+    ResetButtonInputElement,
+    ButtonInputElement
+     native "*HTMLInputElement" {
 
   ///@docsEditable true
   factory InputElement({String type}) {
@@ -10268,11 +10747,480 @@
 
   /// @domName HTMLInputElement.stepUp; @docsEditable true
   void stepUp([int n]) native;
+
 }
 
+
+// Interfaces representing the InputElement APIs which are supported
+// for the various types of InputElement.
+// From http://dev.w3.org/html5/spec/the-input-element.html#the-input-element.
+
+/**
+ * Exposes the functionality common between all InputElement types.
+ */
+abstract class InputElementBase implements Element {
+  /// @domName HTMLInputElement.autofocus
+  bool autofocus;
+
+  /// @domName HTMLInputElement.disabled
+  bool disabled;
+
+  /// @domName HTMLInputElement.incremental
+  bool incremental;
+
+  /// @domName HTMLInputElement.indeterminate
+  bool indeterminate;
+
+  /// @domName HTMLInputElement.labels
+  List<Node> get labels;
+
+  /// @domName HTMLInputElement.name
+  String name;
+
+  /// @domName HTMLInputElement.validationMessage
+  String get validationMessage;
+
+  /// @domName HTMLInputElement.validity
+  ValidityState get validity;
+
+  /// @domName HTMLInputElement.value
+  String value;
+
+  /// @domName HTMLInputElement.willValidate
+  bool get willValidate;
+
+  /// @domName HTMLInputElement.checkValidity
+  bool checkValidity();
+
+  /// @domName HTMLInputElement.setCustomValidity
+  void setCustomValidity(String error);
+}
+
+/**
+ * Hidden input which is not intended to be seen or edited by the user.
+ */
+abstract class HiddenInputElement implements Element {
+  factory HiddenInputElement() => new InputElement(type: 'hidden');
+}
+
+
+/**
+ * Base interface for all inputs which involve text editing.
+ */
+abstract class TextInputElementBase implements InputElementBase {
+  /// @domName HTMLInputElement.autocomplete
+  String autocomplete;
+
+  /// @domName HTMLInputElement.maxLength
+  int maxLength;
+
+  /// @domName HTMLInputElement.pattern
+  String pattern;
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.size
+  int size;
+
+  /// @domName HTMLInputElement.select
+  void select();
+
+  /// @domName HTMLInputElement.selectionDirection
+  String selectionDirection;
+
+  /// @domName HTMLInputElement.selectionEnd
+  int selectionEnd;
+
+  /// @domName HTMLInputElement.selectionStart
+  int selectionStart;
+
+  /// @domName HTMLInputElement.setSelectionRange
+  void setSelectionRange(int start, int end, [String direction]);
+}
+
+/**
+ * Similar to [TextInputElement], but on platforms where search is styled
+ * differently this will get the search style.
+ */
+abstract class SearchInputElement implements TextInputElementBase {
+  factory SearchInputElement() => new InputElement(type: 'search');
+
+  /// @domName HTMLInputElement.dirName;
+  String dirName;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * A basic text input editor control.
+ */
+abstract class TextInputElement implements TextInputElementBase {
+  factory TextInputElement() => new InputElement(type: 'text');
+
+  /// @domName HTMLInputElement.dirName;
+  String dirName;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * A control for editing an absolute URL.
+ */
+abstract class UrlInputElement implements TextInputElementBase {
+  factory UrlInputElement() => new InputElement(type: 'url');
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * Represents a control for editing a telephone number.
+ *
+ * This provides a single line of text with minimal formatting help since
+ * there is a wide variety of telephone numbers.
+ */
+abstract class TelephoneInputElement implements TextInputElementBase {
+  factory TelephoneInputElement() => new InputElement(type: 'tel');
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * An e-mail address or list of e-mail addresses.
+ */
+abstract class EmailInputElement implements TextInputElementBase {
+  factory EmailInputElement() => new InputElement(type: 'email');
+
+  /// @domName HTMLInputElement.autocomplete
+  String autocomplete;
+
+  /// @domName HTMLInputElement.autofocus
+  bool autofocus;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+
+  /// @domName HTMLInputElement.maxLength
+  int maxLength;
+
+  /// @domName HTMLInputElement.multiple;
+  bool multiple;
+
+  /// @domName HTMLInputElement.pattern
+  String pattern;
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.size
+  int size;
+}
+
+/**
+ * Text with no line breaks (sensitive information).
+ */
+abstract class PasswordInputElement implements TextInputElementBase {
+  factory PasswordInputElement() => new InputElement(type: 'password');
+}
+
+/**
+ * Base interface for all input element types which involve ranges.
+ */
+abstract class RangeInputElementBase implements InputElementBase {
+
+  /// @domName HTMLInputElement.list
+  Element get list;
+
+  /// @domName HTMLInputElement.max
+  String max;
+
+  /// @domName HTMLInputElement.min
+  String min;
+
+  /// @domName HTMLInputElement.step
+  String step;
+
+  /// @domName HTMLInputElement.valueAsNumber
+  num valueAsNumber;
+
+  /// @domName HTMLInputElement.stepDown
+  void stepDown([int n]);
+
+  /// @domName HTMLInputElement.stepUp
+  void stepUp([int n]);
+}
+
+/**
+ * A date and time (year, month, day, hour, minute, second, fraction of a
+ * second) with the time zone set to UTC.
+ */
+abstract class DateTimeInputElement implements RangeInputElementBase {
+  factory DateTimeInputElement() => new InputElement(type: 'datetime');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date (year, month, day) with no time zone.
+ */
+abstract class DateInputElement implements RangeInputElementBase {
+  factory DateInputElement() => new InputElement(type: 'date');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date consisting of a year and a month with no time zone.
+ */
+abstract class MonthInputElement implements RangeInputElementBase {
+  factory MonthInputElement() => new InputElement(type: 'month');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date consisting of a week-year number and a week number with no time zone.
+ */
+abstract class WeekInputElement implements RangeInputElementBase {
+  factory WeekInputElement() => new InputElement(type: 'week');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A time (hour, minute, seconds, fractional seconds) with no time zone.
+ */
+abstract class TimeInputElement implements RangeInputElementBase {
+  factory TimeInputElement() => new InputElement(type: 'time');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date and time (year, month, day, hour, minute, second, fraction of a
+ * second) with no time zone.
+ */
+abstract class LocalDateTimeInputElement implements RangeInputElementBase {
+  factory LocalDateTimeInputElement() =>
+      new InputElement(type: 'datetime-local');
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A numeric editor control.
+ */
+abstract class NumberInputElement implements RangeInputElementBase {
+  factory NumberInputElement() => new InputElement(type: 'number');
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * Similar to [NumberInputElement] but the browser may provide more optimal
+ * styling (such as a slider control).
+ */
+abstract class RangeInputElement implements RangeInputElementBase {
+  factory RangeInputElement() => new InputElement(type: 'range');
+}
+
+/**
+ * A boolean editor control.
+ *
+ * Note that if [indeterminate] is set then this control is in a third
+ * indeterminate state.
+ */
+abstract class CheckboxInputElement implements InputElementBase {
+  factory CheckboxInputElement() => new InputElement(type: 'checkbox');
+
+  /// @domName HTMLInputElement.checked
+  bool checked;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+
+/**
+ * A control that when used with other [ReadioButtonInputElement] controls
+ * forms a radio button group in which only one control can be checked at a
+ * time.
+ *
+ * Radio buttons are considered to be in the same radio button group if:
+ *
+ * * They are all of type 'radio'.
+ * * They all have either the same [FormElement] owner, or no owner.
+ * * Their name attributes contain the same name.
+ */
+abstract class RadioButtonInputElement implements InputElementBase {
+  factory RadioButtonInputElement() => new InputElement(type: 'radio');
+
+  /// @domName HTMLInputElement.checked
+  bool checked;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A control for picking files from the user's computer.
+ */
+abstract class FileUploadInputElement implements InputElementBase {
+  factory FileUploadInputElement() => new InputElement(type: 'file');
+
+  /// @domName HTMLInputElement.accept
+  String accept;
+
+  /// @domName HTMLInputElement.multiple
+  bool multiple;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.files
+  List<File> files;
+}
+
+/**
+ * A button, which when clicked, submits the form.
+ */
+abstract class SubmitButtonInputElement implements InputElementBase {
+  factory SubmitButtonInputElement() => new InputElement(type: 'submit');
+
+  /// @domName HTMLInputElement.formAction
+  String formAction;
+
+  /// @domName HTMLInputElement.formEnctype
+  String formEnctype;
+
+  /// @domName HTMLInputElement.formMethod
+  String formMethod;
+
+  /// @domName HTMLInputElement.formNoValidate
+  bool formNoValidate;
+
+  /// @domName HTMLInputElement.formTarget
+  String formTarget;
+}
+
+/**
+ * Either an image which the user can select a coordinate to or a form
+ * submit button.
+ */
+abstract class ImageButtonInputElement implements InputElementBase {
+  factory ImageButtonInputElement() => new InputElement(type: 'image');
+
+  /// @domName HTMLInputElement.alt
+  String alt;
+
+  /// @domName HTMLInputElement.formAction
+  String formAction;
+
+  /// @domName HTMLInputElement.formEnctype
+  String formEnctype;
+
+  /// @domName HTMLInputElement.formMethod
+  String formMethod;
+
+  /// @domName HTMLInputElement.formNoValidate
+  bool formNoValidate;
+
+  /// @domName HTMLInputElement.formTarget
+  String formTarget;
+
+  /// @domName HTMLInputElement.height
+  int height;
+
+  /// @domName HTMLInputElement.src
+  String src;
+
+  /// @domName HTMLInputElement.width
+  int width;
+}
+
+/**
+ * A button, which when clicked, resets the form.
+ */
+abstract class ResetButtonInputElement implements InputElementBase {
+  factory ResetButtonInputElement() => new InputElement(type: 'reset');
+}
+
+/**
+ * A button, with no default behavior.
+ */
+abstract class ButtonInputElement implements InputElementBase {
+  factory ButtonInputElement() => new InputElement(type: 'button');
+}
+
+
+/// @docsEditable true
 class InputElementEvents extends ElementEvents {
+  /// @docsEditable true
   InputElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get speechChange => this['webkitSpeechChange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -10778,7 +11726,7 @@
 
 
 /// @domName HTMLKeygenElement; @docsEditable true
-class KeygenElement extends Element implements Element native "*HTMLKeygenElement" {
+class KeygenElement extends Element native "*HTMLKeygenElement" {
 
   ///@docsEditable true
   factory KeygenElement() => document.$dom_createElement("keygen");
@@ -10829,7 +11777,7 @@
 
 
 /// @domName HTMLLIElement; @docsEditable true
-class LIElement extends Element implements Element native "*HTMLLIElement" {
+class LIElement extends Element native "*HTMLLIElement" {
 
   ///@docsEditable true
   factory LIElement() => document.$dom_createElement("li");
@@ -10846,7 +11794,7 @@
 
 
 /// @domName HTMLLabelElement; @docsEditable true
-class LabelElement extends Element implements Element native "*HTMLLabelElement" {
+class LabelElement extends Element native "*HTMLLabelElement" {
 
   ///@docsEditable true
   factory LabelElement() => document.$dom_createElement("label");
@@ -10866,7 +11814,7 @@
 
 
 /// @domName HTMLLegendElement; @docsEditable true
-class LegendElement extends Element implements Element native "*HTMLLegendElement" {
+class LegendElement extends Element native "*HTMLLegendElement" {
 
   ///@docsEditable true
   factory LegendElement() => document.$dom_createElement("legend");
@@ -10883,7 +11831,7 @@
 
 
 /// @domName HTMLLinkElement; @docsEditable true
-class LinkElement extends Element implements Element native "*HTMLLinkElement" {
+class LinkElement extends Element native "*HTMLLinkElement" {
 
   ///@docsEditable true
   factory LinkElement() => document.$dom_createElement("link");
@@ -11451,153 +12399,228 @@
 
 }
 
+/// @docsEditable true
 class LocalWindowEvents extends Events {
+  /// @docsEditable true
   LocalWindowEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get beforeUnload => this['beforeunload'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get canPlay => this['canplay'];
 
+  /// @docsEditable true
   EventListenerList get canPlayThrough => this['canplaythrough'];
 
+  /// @docsEditable true
   EventListenerList get change => this['change'];
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get contextMenu => this['contextmenu'];
 
+  /// @docsEditable true
   EventListenerList get doubleClick => this['dblclick'];
 
+  /// @docsEditable true
   EventListenerList get deviceMotion => this['devicemotion'];
 
+  /// @docsEditable true
   EventListenerList get deviceOrientation => this['deviceorientation'];
 
+  /// @docsEditable true
   EventListenerList get drag => this['drag'];
 
+  /// @docsEditable true
   EventListenerList get dragEnd => this['dragend'];
 
+  /// @docsEditable true
   EventListenerList get dragEnter => this['dragenter'];
 
+  /// @docsEditable true
   EventListenerList get dragLeave => this['dragleave'];
 
+  /// @docsEditable true
   EventListenerList get dragOver => this['dragover'];
 
+  /// @docsEditable true
   EventListenerList get dragStart => this['dragstart'];
 
+  /// @docsEditable true
   EventListenerList get drop => this['drop'];
 
+  /// @docsEditable true
   EventListenerList get durationChange => this['durationchange'];
 
+  /// @docsEditable true
   EventListenerList get emptied => this['emptied'];
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get hashChange => this['hashchange'];
 
+  /// @docsEditable true
   EventListenerList get input => this['input'];
 
+  /// @docsEditable true
   EventListenerList get invalid => this['invalid'];
 
+  /// @docsEditable true
   EventListenerList get keyDown => this['keydown'];
 
+  /// @docsEditable true
   EventListenerList get keyPress => this['keypress'];
 
+  /// @docsEditable true
   EventListenerList get keyUp => this['keyup'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get loadedData => this['loadeddata'];
 
+  /// @docsEditable true
   EventListenerList get loadedMetadata => this['loadedmetadata'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get mouseDown => this['mousedown'];
 
+  /// @docsEditable true
   EventListenerList get mouseMove => this['mousemove'];
 
+  /// @docsEditable true
   EventListenerList get mouseOut => this['mouseout'];
 
+  /// @docsEditable true
   EventListenerList get mouseOver => this['mouseover'];
 
+  /// @docsEditable true
   EventListenerList get mouseUp => this['mouseup'];
 
+  /// @docsEditable true
   EventListenerList get mouseWheel => this['mousewheel'];
 
+  /// @docsEditable true
   EventListenerList get offline => this['offline'];
 
+  /// @docsEditable true
   EventListenerList get online => this['online'];
 
+  /// @docsEditable true
   EventListenerList get pageHide => this['pagehide'];
 
+  /// @docsEditable true
   EventListenerList get pageShow => this['pageshow'];
 
+  /// @docsEditable true
   EventListenerList get pause => this['pause'];
 
+  /// @docsEditable true
   EventListenerList get play => this['play'];
 
+  /// @docsEditable true
   EventListenerList get playing => this['playing'];
 
+  /// @docsEditable true
   EventListenerList get popState => this['popstate'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get rateChange => this['ratechange'];
 
+  /// @docsEditable true
   EventListenerList get reset => this['reset'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get scroll => this['scroll'];
 
+  /// @docsEditable true
   EventListenerList get search => this['search'];
 
+  /// @docsEditable true
   EventListenerList get seeked => this['seeked'];
 
+  /// @docsEditable true
   EventListenerList get seeking => this['seeking'];
 
+  /// @docsEditable true
   EventListenerList get select => this['select'];
 
+  /// @docsEditable true
   EventListenerList get stalled => this['stalled'];
 
+  /// @docsEditable true
   EventListenerList get storage => this['storage'];
 
+  /// @docsEditable true
   EventListenerList get submit => this['submit'];
 
+  /// @docsEditable true
   EventListenerList get suspend => this['suspend'];
 
+  /// @docsEditable true
   EventListenerList get timeUpdate => this['timeupdate'];
 
+  /// @docsEditable true
   EventListenerList get touchCancel => this['touchcancel'];
 
+  /// @docsEditable true
   EventListenerList get touchEnd => this['touchend'];
 
+  /// @docsEditable true
   EventListenerList get touchMove => this['touchmove'];
 
+  /// @docsEditable true
   EventListenerList get touchStart => this['touchstart'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 
+  /// @docsEditable true
   EventListenerList get volumeChange => this['volumechange'];
 
+  /// @docsEditable true
   EventListenerList get waiting => this['waiting'];
 
+  /// @docsEditable true
   EventListenerList get animationEnd => this['webkitAnimationEnd'];
 
+  /// @docsEditable true
   EventListenerList get animationIteration => this['webkitAnimationIteration'];
 
+  /// @docsEditable true
   EventListenerList get animationStart => this['webkitAnimationStart'];
 
+  /// @docsEditable true
   EventListenerList get transitionEnd => this['webkitTransitionEnd'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -11606,7 +12629,7 @@
 
 
 /// @domName HTMLMapElement; @docsEditable true
-class MapElement extends Element implements Element native "*HTMLMapElement" {
+class MapElement extends Element native "*HTMLMapElement" {
 
   ///@docsEditable true
   factory MapElement() => document.$dom_createElement("map");
@@ -11623,7 +12646,7 @@
 
 
 /// @domName HTMLMarqueeElement; @docsEditable true
-class MarqueeElement extends Element implements Element native "*HTMLMarqueeElement" {
+class MarqueeElement extends Element native "*HTMLMarqueeElement" {
 
   /// @domName HTMLMarqueeElement.behavior; @docsEditable true
   String behavior;
@@ -11729,7 +12752,7 @@
 
 
 /// @domName HTMLMediaElement; @docsEditable true
-class MediaElement extends Element implements Element native "*HTMLMediaElement" {
+class MediaElement extends Element native "*HTMLMediaElement" {
 
   /// @domName EventTarget.addEventListener, EventTarget.removeEventListener, EventTarget.dispatchEvent; @docsEditable true
   MediaElementEvents get on =>
@@ -11874,57 +12897,84 @@
   void webkitGenerateKeyRequest(String keySystem, [Uint8Array initData]) native;
 }
 
+/// @docsEditable true
 class MediaElementEvents extends ElementEvents {
+  /// @docsEditable true
   MediaElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get canPlay => this['canplay'];
 
+  /// @docsEditable true
   EventListenerList get canPlayThrough => this['canplaythrough'];
 
+  /// @docsEditable true
   EventListenerList get durationChange => this['durationchange'];
 
+  /// @docsEditable true
   EventListenerList get emptied => this['emptied'];
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 
+  /// @docsEditable true
   EventListenerList get loadedData => this['loadeddata'];
 
+  /// @docsEditable true
   EventListenerList get loadedMetadata => this['loadedmetadata'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get pause => this['pause'];
 
+  /// @docsEditable true
   EventListenerList get play => this['play'];
 
+  /// @docsEditable true
   EventListenerList get playing => this['playing'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get rateChange => this['ratechange'];
 
+  /// @docsEditable true
   EventListenerList get seeked => this['seeked'];
 
+  /// @docsEditable true
   EventListenerList get seeking => this['seeking'];
 
+  /// @docsEditable true
   EventListenerList get show => this['show'];
 
+  /// @docsEditable true
   EventListenerList get stalled => this['stalled'];
 
+  /// @docsEditable true
   EventListenerList get suspend => this['suspend'];
 
+  /// @docsEditable true
   EventListenerList get timeUpdate => this['timeupdate'];
 
+  /// @docsEditable true
   EventListenerList get volumeChange => this['volumechange'];
 
+  /// @docsEditable true
   EventListenerList get waiting => this['waiting'];
 
+  /// @docsEditable true
   EventListenerList get keyAdded => this['webkitkeyadded'];
 
+  /// @docsEditable true
   EventListenerList get keyError => this['webkitkeyerror'];
 
+  /// @docsEditable true
   EventListenerList get keyMessage => this['webkitkeymessage'];
 
+  /// @docsEditable true
   EventListenerList get needKey => this['webkitneedkey'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12143,9 +13193,12 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class MediaStreamEvents extends Events {
+  /// @docsEditable true
   MediaStreamEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12202,13 +13255,18 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class MediaStreamTrackEvents extends Events {
+  /// @docsEditable true
   MediaStreamTrackEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 
+  /// @docsEditable true
   EventListenerList get mute => this['mute'];
 
+  /// @docsEditable true
   EventListenerList get unmute => this['unmute'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12259,11 +13317,15 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class MediaStreamTrackListEvents extends Events {
+  /// @docsEditable true
   MediaStreamTrackListEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addTrack => this['addtrack'];
 
+  /// @docsEditable true
   EventListenerList get removeTrack => this['removetrack'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12288,8 +13350,18 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+/**
+ * An HTML <menu> element.
+ *
+ * A <menu> element represents an unordered list of menu commands.
+ *
+ * See also:
+ *
+ *  * [Menu Element](https://developer.mozilla.org/en-US/docs/HTML/Element/menu) from MDN.
+ *  * [Menu Element](http://www.w3.org/TR/html5/the-menu-element.html#the-menu-element) from the W3C.
+ */
 /// @domName HTMLMenuElement; @docsEditable true
-class MenuElement extends Element implements Element native "*HTMLMenuElement" {
+class MenuElement extends Element native "*HTMLMenuElement" {
 
   ///@docsEditable true
   factory MenuElement() => document.$dom_createElement("menu");
@@ -12394,9 +13466,12 @@
   void start() native;
 }
 
+/// @docsEditable true
 class MessagePortEvents extends Events {
+  /// @docsEditable true
   MessagePortEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12405,7 +13480,7 @@
 
 
 /// @domName HTMLMetaElement; @docsEditable true
-class MetaElement extends Element implements Element native "*HTMLMetaElement" {
+class MetaElement extends Element native "*HTMLMetaElement" {
 
   /// @domName HTMLMetaElement.content; @docsEditable true
   String content;
@@ -12447,7 +13522,7 @@
 
 
 /// @domName HTMLMeterElement; @docsEditable true
-class MeterElement extends Element implements Element native "*HTMLMeterElement" {
+class MeterElement extends Element native "*HTMLMeterElement" {
 
   ///@docsEditable true
   factory MeterElement() => document.$dom_createElement("meter");
@@ -12480,7 +13555,7 @@
 
 
 /// @domName HTMLModElement; @docsEditable true
-class ModElement extends Element implements Element native "*HTMLModElement" {
+class ModElement extends Element native "*HTMLModElement" {
 
   /// @domName HTMLModElement.cite; @docsEditable true
   String cite;
@@ -13157,9 +14232,9 @@
   void remove() {
     // TODO(jacobr): should we throw an exception if parent is already null?
     // TODO(vsm): Use the native remove when available.
-    if (this.parent != null) {
-      final Node parent = this.parent;
-      parent.$dom_removeChild(this);
+    if (this.parentNode != null) {
+      final Node parent = this.parentNode;
+      parentNode.$dom_removeChild(this);
     }
   }
 
@@ -13169,7 +14244,7 @@
    */
   Node replaceWith(Node otherNode) {
     try {
-      final Node parent = this.parent;
+      final Node parent = this.parentNode;
       parent.$dom_replaceChild(otherNode, this);
     } catch (e) {
 
@@ -13250,9 +14325,12 @@
   @JSName('ownerDocument')
   final Document document;
 
+  /// @domName Node.parentElement; @docsEditable true
+  @JSName('parentElement')
+  final Element parent;
+
   /// @domName Node.parentNode; @docsEditable true
-  @JSName('parentNode')
-  final Node parent;
+  final Node parentNode;
 
   /// @domName Node.previousSibling; @docsEditable true
   @JSName('previousSibling')
@@ -13564,17 +14642,24 @@
   void show() native;
 }
 
+/// @docsEditable true
 class NotificationEvents extends Events {
+  /// @docsEditable true
   NotificationEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get close => this['close'];
 
+  /// @docsEditable true
   EventListenerList get display => this['display'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get show => this['show'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -13612,7 +14697,7 @@
 
 
 /// @domName HTMLOListElement; @docsEditable true
-class OListElement extends Element implements Element native "*HTMLOListElement" {
+class OListElement extends Element native "*HTMLOListElement" {
 
   ///@docsEditable true
   factory OListElement() => document.$dom_createElement("ol");
@@ -13635,7 +14720,7 @@
 
 
 /// @domName HTMLObjectElement; @docsEditable true
-class ObjectElement extends Element implements Element native "*HTMLObjectElement" {
+class ObjectElement extends Element native "*HTMLObjectElement" {
 
   ///@docsEditable true
   factory ObjectElement() => document.$dom_createElement("object");
@@ -13764,7 +14849,7 @@
 
 
 /// @domName HTMLOptGroupElement; @docsEditable true
-class OptGroupElement extends Element implements Element native "*HTMLOptGroupElement" {
+class OptGroupElement extends Element native "*HTMLOptGroupElement" {
 
   ///@docsEditable true
   factory OptGroupElement() => document.$dom_createElement("optgroup");
@@ -13781,7 +14866,7 @@
 
 
 /// @domName HTMLOptionElement; @docsEditable true
-class OptionElement extends Element implements Element native "*HTMLOptionElement" {
+class OptionElement extends Element native "*HTMLOptionElement" {
 
   ///@docsEditable true
   factory OptionElement([String data, String value, bool defaultSelected, bool selected]) {
@@ -13827,7 +14912,7 @@
 
 
 /// @domName HTMLOutputElement; @docsEditable true
-class OutputElement extends Element implements Element native "*HTMLOutputElement" {
+class OutputElement extends Element native "*HTMLOutputElement" {
 
   ///@docsEditable true
   factory OutputElement() => document.$dom_createElement("output");
@@ -13923,7 +15008,7 @@
 
 
 /// @domName HTMLParagraphElement; @docsEditable true
-class ParagraphElement extends Element implements Element native "*HTMLParagraphElement" {
+class ParagraphElement extends Element native "*HTMLParagraphElement" {
 
   ///@docsEditable true
   factory ParagraphElement() => document.$dom_createElement("p");
@@ -13937,7 +15022,7 @@
 
 
 /// @domName HTMLParamElement; @docsEditable true
-class ParamElement extends Element implements Element native "*HTMLParamElement" {
+class ParamElement extends Element native "*HTMLParamElement" {
 
   ///@docsEditable true
   factory ParamElement() => document.$dom_createElement("param");
@@ -14101,17 +15186,24 @@
   void _startIce_2() native;
 }
 
+/// @docsEditable true
 class PeerConnection00Events extends Events {
+  /// @docsEditable true
   PeerConnection00Events(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addStream => this['addstream'];
 
+  /// @docsEditable true
   EventListenerList get connecting => this['connecting'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 
+  /// @docsEditable true
   EventListenerList get removeStream => this['removestream'];
 
+  /// @docsEditable true
   EventListenerList get stateChange => this['statechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -14301,7 +15393,7 @@
 
 
 /// @domName HTMLPreElement; @docsEditable true
-class PreElement extends Element implements Element native "*HTMLPreElement" {
+class PreElement extends Element native "*HTMLPreElement" {
 
   ///@docsEditable true
   factory PreElement() => document.$dom_createElement("pre");
@@ -14335,7 +15427,7 @@
 
 
 /// @domName HTMLProgressElement; @docsEditable true
-class ProgressElement extends Element implements Element native "*HTMLProgressElement" {
+class ProgressElement extends Element native "*HTMLProgressElement" {
 
   ///@docsEditable true
   factory ProgressElement() => document.$dom_createElement("progress");
@@ -14376,7 +15468,7 @@
 
 
 /// @domName HTMLQuoteElement; @docsEditable true
-class QuoteElement extends Element implements Element native "*HTMLQuoteElement" {
+class QuoteElement extends Element native "*HTMLQuoteElement" {
 
   /// @domName HTMLQuoteElement.cite; @docsEditable true
   String cite;
@@ -14654,15 +15746,21 @@
   void send(data) native;
 }
 
+/// @docsEditable true
 class RtcDataChannelEvents extends Events {
+  /// @docsEditable true
   RtcDataChannelEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get close => this['close'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -14859,21 +15957,30 @@
   void _updateIce_3() native;
 }
 
+/// @docsEditable true
 class RtcPeerConnectionEvents extends Events {
+  /// @docsEditable true
   RtcPeerConnectionEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addStream => this['addstream'];
 
+  /// @docsEditable true
   EventListenerList get iceCandidate => this['icecandidate'];
 
+  /// @docsEditable true
   EventListenerList get iceChange => this['icechange'];
 
+  /// @docsEditable true
   EventListenerList get negotiationNeeded => this['negotiationneeded'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 
+  /// @docsEditable true
   EventListenerList get removeStream => this['removestream'];
 
+  /// @docsEditable true
   EventListenerList get stateChange => this['statechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -15010,7 +16117,7 @@
 
 
 /// @domName HTMLScriptElement; @docsEditable true
-class ScriptElement extends Element implements Element native "*HTMLScriptElement" {
+class ScriptElement extends Element native "*HTMLScriptElement" {
 
   ///@docsEditable true
   factory ScriptElement() => document.$dom_createElement("script");
@@ -15098,7 +16205,7 @@
 
 
 /// @domName HTMLSelectElement
-class SelectElement extends Element implements Element native "*HTMLSelectElement" {
+class SelectElement extends Element native "*HTMLSelectElement" {
 
   ///@docsEditable true
   factory SelectElement() => document.$dom_createElement("select");
@@ -15200,7 +16307,7 @@
 
 
 /// @domName HTMLShadowElement; @docsEditable true
-class ShadowElement extends Element implements Element native "*HTMLShadowElement" {
+class ShadowElement extends Element native "*HTMLShadowElement" {
 
   /// @domName HTMLShadowElement.resetStyleInheritance; @docsEditable true
   bool resetStyleInheritance;
@@ -15290,9 +16397,12 @@
   final String name;
 }
 
+/// @docsEditable true
 class SharedWorkerContextEvents extends WorkerContextEvents {
+  /// @docsEditable true
   SharedWorkerContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get connect => this['connect'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -15447,7 +16557,7 @@
 
 
 /// @domName HTMLSourceElement; @docsEditable true
-class SourceElement extends Element implements Element native "*HTMLSourceElement" {
+class SourceElement extends Element native "*HTMLSourceElement" {
 
   ///@docsEditable true
   factory SourceElement() => document.$dom_createElement("source");
@@ -15467,7 +16577,7 @@
 
 
 /// @domName HTMLSpanElement; @docsEditable true
-class SpanElement extends Element implements Element native "*HTMLSpanElement" {
+class SpanElement extends Element native "*HTMLSpanElement" {
 
   ///@docsEditable true
   factory SpanElement() => document.$dom_createElement("span");
@@ -15690,29 +16800,42 @@
   void stop() native;
 }
 
+/// @docsEditable true
 class SpeechRecognitionEvents extends Events {
+  /// @docsEditable true
   SpeechRecognitionEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get audioEnd => this['audioend'];
 
+  /// @docsEditable true
   EventListenerList get audioStart => this['audiostart'];
 
+  /// @docsEditable true
   EventListenerList get end => this['end'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get noMatch => this['nomatch'];
 
+  /// @docsEditable true
   EventListenerList get result => this['result'];
 
+  /// @docsEditable true
   EventListenerList get soundEnd => this['soundend'];
 
+  /// @docsEditable true
   EventListenerList get soundStart => this['soundstart'];
 
+  /// @docsEditable true
   EventListenerList get speechEnd => this['speechend'];
 
+  /// @docsEditable true
   EventListenerList get speechStart => this['speechstart'];
 
+  /// @docsEditable true
   EventListenerList get start => this['start'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -16180,7 +17303,7 @@
 
 
 /// @domName HTMLStyleElement; @docsEditable true
-class StyleElement extends Element implements Element native "*HTMLStyleElement" {
+class StyleElement extends Element native "*HTMLStyleElement" {
 
   ///@docsEditable true
   factory StyleElement() => document.$dom_createElement("style");
@@ -16249,7 +17372,7 @@
 
 
 /// @domName HTMLTableCaptionElement; @docsEditable true
-class TableCaptionElement extends Element implements Element native "*HTMLTableCaptionElement" {
+class TableCaptionElement extends Element native "*HTMLTableCaptionElement" {
 
   ///@docsEditable true
   factory TableCaptionElement() => document.$dom_createElement("caption");
@@ -16263,7 +17386,7 @@
 
 
 /// @domName HTMLTableCellElement; @docsEditable true
-class TableCellElement extends Element implements Element native "*HTMLTableCellElement" {
+class TableCellElement extends Element native "*HTMLTableCellElement" {
 
   ///@docsEditable true
   factory TableCellElement() => document.$dom_createElement("td");
@@ -16319,7 +17442,7 @@
 
 
 /// @domName HTMLTableColElement; @docsEditable true
-class TableColElement extends Element implements Element native "*HTMLTableColElement" {
+class TableColElement extends Element native "*HTMLTableColElement" {
 
   ///@docsEditable true
   factory TableColElement() => document.$dom_createElement("col");
@@ -16348,7 +17471,7 @@
 
 
 /// @domName HTMLTableElement
-class TableElement extends Element implements Element native "*HTMLTableElement" {
+class TableElement extends Element native "*HTMLTableElement" {
 
   ///@docsEditable true
   factory TableElement() => document.$dom_createElement("table");
@@ -16438,7 +17561,7 @@
 
 
 /// @domName HTMLTableRowElement; @docsEditable true
-class TableRowElement extends Element implements Element native "*HTMLTableRowElement" {
+class TableRowElement extends Element native "*HTMLTableRowElement" {
 
   ///@docsEditable true
   factory TableRowElement() => document.$dom_createElement("tr");
@@ -16479,7 +17602,7 @@
 
 
 /// @domName HTMLTableSectionElement; @docsEditable true
-class TableSectionElement extends Element implements Element native "*HTMLTableSectionElement" {
+class TableSectionElement extends Element native "*HTMLTableSectionElement" {
 
   /// @domName HTMLTableSectionElement.align; @docsEditable true
   String align;
@@ -16529,7 +17652,7 @@
 
 
 /// @domName HTMLTextAreaElement; @docsEditable true
-class TextAreaElement extends Element implements Element native "*HTMLTextAreaElement" {
+class TextAreaElement extends Element native "*HTMLTextAreaElement" {
 
   ///@docsEditable true
   factory TextAreaElement() => document.$dom_createElement("textarea");
@@ -16693,9 +17816,12 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class TextTrackEvents extends Events {
+  /// @docsEditable true
   TextTrackEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get cueChange => this['cuechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -16766,11 +17892,15 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class TextTrackCueEvents extends Events {
+  /// @docsEditable true
   TextTrackCueEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get enter => this['enter'];
 
+  /// @docsEditable true
   EventListenerList get exit => this['exit'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -17021,9 +18151,12 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class TextTrackListEvents extends Events {
+  /// @docsEditable true
   TextTrackListEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addTrack => this['addtrack'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -17057,7 +18190,7 @@
 
 
 /// @domName HTMLTitleElement; @docsEditable true
-class TitleElement extends Element implements Element native "*HTMLTitleElement" {
+class TitleElement extends Element native "*HTMLTitleElement" {
 
   ///@docsEditable true
   factory TitleElement() => document.$dom_createElement("title");
@@ -17261,7 +18394,7 @@
 
 
 /// @domName HTMLTrackElement; @docsEditable true
-class TrackElement extends Element implements Element native "*HTMLTrackElement" {
+class TrackElement extends Element native "*HTMLTrackElement" {
 
   ///@docsEditable true
   factory TrackElement() => document.$dom_createElement("track");
@@ -17430,7 +18563,7 @@
 
 
 /// @domName HTMLUListElement; @docsEditable true
-class UListElement extends Element implements Element native "*HTMLUListElement" {
+class UListElement extends Element native "*HTMLUListElement" {
 
   ///@docsEditable true
   factory UListElement() => document.$dom_createElement("ul");
@@ -17852,7 +18985,7 @@
 
 
 /// @domName HTMLUnknownElement; @docsEditable true
-class UnknownElement extends Element implements Element native "*HTMLUnknownElement" {
+class UnknownElement extends Element native "*HTMLUnknownElement" {
 }
 // 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
@@ -19405,15 +20538,21 @@
 
 }
 
+/// @docsEditable true
 class WebSocketEvents extends Events {
+  /// @docsEditable true
   WebSocketEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get close => this['close'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -19539,9 +20678,12 @@
   void terminate() native;
 }
 
+/// @docsEditable true
 class WorkerEvents extends AbstractWorkerEvents {
+  /// @docsEditable true
   WorkerEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -19629,9 +20771,12 @@
          this, this, this);
 }
 
+/// @docsEditable true
 class WorkerContextEvents extends Events {
+  /// @docsEditable true
   WorkerContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -22064,7 +23209,7 @@
   String _type;
 
   /** The element we are watching for events to happen on. */
-  Element _target;
+  EventTarget _target;
 
   // The distance to shift from upper case alphabet Roman letters to lower case.
   final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
@@ -22123,7 +23268,7 @@
    * General constructor, performs basic initialization for our improved
    * KeyboardEvent controller.
    */
-  _KeyboardEventController(Element target, String type) {
+  _KeyboardEventController(EventTarget target, String type) {
     _callbacks = [];
     _type = type;
     _target = target;
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 9c67b2f..9f69c01 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -93,9 +93,12 @@
 
 }
 
+/// @docsEditable true
 class AbstractWorkerEvents extends Events {
+  /// @docsEditable true
   AbstractWorkerEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -526,23 +529,33 @@
 
 }
 
+/// @docsEditable true
 class ApplicationCacheEvents extends Events {
+  /// @docsEditable true
   ApplicationCacheEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get cached => this['cached'];
 
+  /// @docsEditable true
   EventListenerList get checking => this['checking'];
 
+  /// @docsEditable true
   EventListenerList get downloading => this['downloading'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get noUpdate => this['noupdate'];
 
+  /// @docsEditable true
   EventListenerList get obsolete => this['obsolete'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get updateReady => this['updateready'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -909,15 +922,21 @@
 
 }
 
+/// @docsEditable true
 class BatteryManagerEvents extends Events {
+  /// @docsEditable true
   BatteryManagerEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get chargingChange => this['chargingchange'];
 
+  /// @docsEditable true
   EventListenerList get chargingTimeChange => this['chargingtimechange'];
 
+  /// @docsEditable true
   EventListenerList get dischargingTimeChange => this['dischargingtimechange'];
 
+  /// @docsEditable true
   EventListenerList get levelChange => this['levelchange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -1056,33 +1075,48 @@
 
 }
 
+/// @docsEditable true
 class BodyElementEvents extends ElementEvents {
+  /// @docsEditable true
   BodyElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get beforeUnload => this['beforeunload'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get hashChange => this['hashchange'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get offline => this['offline'];
 
+  /// @docsEditable true
   EventListenerList get online => this['online'];
 
+  /// @docsEditable true
   EventListenerList get popState => this['popstate'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get storage => this['storage'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -6829,9 +6863,12 @@
 
 }
 
+/// @docsEditable true
 class DedicatedWorkerContextEvents extends WorkerContextEvents {
+  /// @docsEditable true
   DedicatedWorkerContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -7327,15 +7364,21 @@
   }
 }
 
+/// @docsEditable true
 class DocumentEvents extends ElementEvents {
+  /// @docsEditable true
   DocumentEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get readyStateChange => this['readystatechange'];
 
+  /// @docsEditable true
   EventListenerList get selectionChange => this['selectionchange'];
 
+  /// @docsEditable true
   EventListenerList get pointerLockChange => this['webkitpointerlockchange'];
 
+  /// @docsEditable true
   EventListenerList get pointerLockError => this['webkitpointerlockerror'];
 }
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
@@ -7368,9 +7411,11 @@
   factory DocumentFragment.svg(String svgContent) =>
       _DocumentFragmentFactoryProvider.createDocumentFragment_svg(svgContent);
 
+  @deprecated
   List<Element> get elements => this.children;
 
   // TODO: The type of value should be Collection<Element>. See http://b/5392897
+  @deprecated
   void set elements(value) {
     this.children = value;
   }
@@ -7473,12 +7518,12 @@
   String get webkitdropzone => "";
   String get webkitRegionOverflow => "";
   Element get $m_firstElementChild {
-    if (elements.length > 0) {
-      return elements[0];
+    if (children.length > 0) {
+      return children[0];
     }
     return null;
   }
-  Element get $m_lastElementChild => elements.last;
+  Element get $m_lastElementChild => children.last;
   Element get nextElementSibling => null;
   Element get previousElementSibling => null;
   Element get offsetParent => null;
@@ -8806,11 +8851,14 @@
   /**
    * Deprecated, use innerHtml instead.
    */
+  @deprecated
   String get innerHTML => this.innerHtml;
+  @deprecated
   void set innerHTML(String value) {
     this.innerHtml = value;
   }
 
+  @deprecated
   void set elements(Collection<Element> value) {
     this.children = value;
   }
@@ -8818,6 +8866,7 @@
   /**
    * Deprecated, use [children] instead.
    */
+  @deprecated
   List<Element> get elements => this.children;
 
   /**
@@ -9266,103 +9315,153 @@
       document.$dom_createElement(tag);
 }
 
+/// @docsEditable true
 class ElementEvents extends Events {
+  /// @docsEditable true
   ElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get beforeCopy => this['beforecopy'];
 
+  /// @docsEditable true
   EventListenerList get beforeCut => this['beforecut'];
 
+  /// @docsEditable true
   EventListenerList get beforePaste => this['beforepaste'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get change => this['change'];
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get contextMenu => this['contextmenu'];
 
+  /// @docsEditable true
   EventListenerList get copy => this['copy'];
 
+  /// @docsEditable true
   EventListenerList get cut => this['cut'];
 
+  /// @docsEditable true
   EventListenerList get doubleClick => this['dblclick'];
 
+  /// @docsEditable true
   EventListenerList get drag => this['drag'];
 
+  /// @docsEditable true
   EventListenerList get dragEnd => this['dragend'];
 
+  /// @docsEditable true
   EventListenerList get dragEnter => this['dragenter'];
 
+  /// @docsEditable true
   EventListenerList get dragLeave => this['dragleave'];
 
+  /// @docsEditable true
   EventListenerList get dragOver => this['dragover'];
 
+  /// @docsEditable true
   EventListenerList get dragStart => this['dragstart'];
 
+  /// @docsEditable true
   EventListenerList get drop => this['drop'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get input => this['input'];
 
+  /// @docsEditable true
   EventListenerList get invalid => this['invalid'];
 
+  /// @docsEditable true
   EventListenerList get keyDown => this['keydown'];
 
+  /// @docsEditable true
   EventListenerList get keyPress => this['keypress'];
 
+  /// @docsEditable true
   EventListenerList get keyUp => this['keyup'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get mouseDown => this['mousedown'];
 
+  /// @docsEditable true
   EventListenerList get mouseMove => this['mousemove'];
 
+  /// @docsEditable true
   EventListenerList get mouseOut => this['mouseout'];
 
+  /// @docsEditable true
   EventListenerList get mouseOver => this['mouseover'];
 
+  /// @docsEditable true
   EventListenerList get mouseUp => this['mouseup'];
 
+  /// @docsEditable true
   EventListenerList get mouseWheel => this['mousewheel'];
 
+  /// @docsEditable true
   EventListenerList get paste => this['paste'];
 
+  /// @docsEditable true
   EventListenerList get reset => this['reset'];
 
+  /// @docsEditable true
   EventListenerList get scroll => this['scroll'];
 
+  /// @docsEditable true
   EventListenerList get search => this['search'];
 
+  /// @docsEditable true
   EventListenerList get select => this['select'];
 
+  /// @docsEditable true
   EventListenerList get selectStart => this['selectstart'];
 
+  /// @docsEditable true
   EventListenerList get submit => this['submit'];
 
+  /// @docsEditable true
   EventListenerList get touchCancel => this['touchcancel'];
 
+  /// @docsEditable true
   EventListenerList get touchEnd => this['touchend'];
 
+  /// @docsEditable true
   EventListenerList get touchEnter => this['touchenter'];
 
+  /// @docsEditable true
   EventListenerList get touchLeave => this['touchleave'];
 
+  /// @docsEditable true
   EventListenerList get touchMove => this['touchmove'];
 
+  /// @docsEditable true
   EventListenerList get touchStart => this['touchstart'];
 
+  /// @docsEditable true
   EventListenerList get transitionEnd => this['webkitTransitionEnd'];
 
+  /// @docsEditable true
   EventListenerList get fullscreenChange => this['webkitfullscreenchange'];
 
+  /// @docsEditable true
   EventListenerList get fullscreenError => this['webkitfullscreenerror'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -9866,13 +9965,18 @@
 
 }
 
+/// @docsEditable true
 class EventSourceEvents extends Events {
+  /// @docsEditable true
   EventSourceEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -10414,19 +10518,27 @@
 
 }
 
+/// @docsEditable true
 class FileReaderEvents extends Events {
+  /// @docsEditable true
   FileReaderEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get loadEnd => this['loadend'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -10586,19 +10698,27 @@
 
 }
 
+/// @docsEditable true
 class FileWriterEvents extends Events {
+  /// @docsEditable true
   FileWriterEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get write => this['write'];
 
+  /// @docsEditable true
   EventListenerList get writeEnd => this['writeend'];
 
+  /// @docsEditable true
   EventListenerList get writeStart => this['writestart'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -10994,7 +11114,7 @@
 
 
   /** @domName DOMFormData.append */
-  void append(String name, String value, String filename) native "DOMFormData_append_Callback";
+  void append(String name, value, [String filename]) native "DOMFormData_append_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -11229,33 +11349,48 @@
 
 }
 
+/// @docsEditable true
 class FrameSetElementEvents extends ElementEvents {
+  /// @docsEditable true
   FrameSetElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get beforeUnload => this['beforeunload'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get hashChange => this['hashchange'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get offline => this['offline'];
 
+  /// @docsEditable true
   EventListenerList get online => this['online'];
 
+  /// @docsEditable true
   EventListenerList get popState => this['popstate'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get storage => this['storage'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12032,21 +12167,30 @@
 
 }
 
+/// @docsEditable true
 class HttpRequestEvents extends Events {
+  /// @docsEditable true
   HttpRequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get loadEnd => this['loadend'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get readyStateChange => this['readystatechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12130,19 +12274,27 @@
 
 }
 
+/// @docsEditable true
 class HttpRequestUploadEvents extends Events {
+  /// @docsEditable true
   HttpRequestUploadEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get loadEnd => this['loadend'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12472,11 +12624,32 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 
 /// @domName HTMLInputElement
-class InputElement extends _Element_Merged {
+class InputElement extends _Element_Merged implements
+    HiddenInputElement,
+    SearchInputElement,
+    TextInputElement,
+    UrlInputElement,
+    TelephoneInputElement,
+    EmailInputElement,
+    PasswordInputElement,
+    DateTimeInputElement,
+    DateInputElement,
+    MonthInputElement,
+    WeekInputElement,
+    TimeInputElement,
+    LocalDateTimeInputElement,
+    NumberInputElement,
+    RangeInputElement,
+    CheckboxInputElement,
+    RadioButtonInputElement,
+    FileUploadInputElement,
+    SubmitButtonInputElement,
+    ImageButtonInputElement,
+    ResetButtonInputElement,
+    ButtonInputElement
+     {
 
   ///@docsEditable true
   factory InputElement({String type}) {
@@ -12932,9 +13105,477 @@
 
 }
 
+
+// Interfaces representing the InputElement APIs which are supported
+// for the various types of InputElement.
+// From http://dev.w3.org/html5/spec/the-input-element.html#the-input-element.
+
+/**
+ * Exposes the functionality common between all InputElement types.
+ */
+abstract class InputElementBase implements Element {
+  /// @domName HTMLInputElement.autofocus
+  bool autofocus;
+
+  /// @domName HTMLInputElement.disabled
+  bool disabled;
+
+  /// @domName HTMLInputElement.incremental
+  bool incremental;
+
+  /// @domName HTMLInputElement.indeterminate
+  bool indeterminate;
+
+  /// @domName HTMLInputElement.labels
+  List<Node> get labels;
+
+  /// @domName HTMLInputElement.name
+  String name;
+
+  /// @domName HTMLInputElement.validationMessage
+  String get validationMessage;
+
+  /// @domName HTMLInputElement.validity
+  ValidityState get validity;
+
+  /// @domName HTMLInputElement.value
+  String value;
+
+  /// @domName HTMLInputElement.willValidate
+  bool get willValidate;
+
+  /// @domName HTMLInputElement.checkValidity
+  bool checkValidity();
+
+  /// @domName HTMLInputElement.setCustomValidity
+  void setCustomValidity(String error);
+}
+
+/**
+ * Hidden input which is not intended to be seen or edited by the user.
+ */
+abstract class HiddenInputElement implements Element {
+  factory HiddenInputElement() => new InputElement(type: 'hidden');
+}
+
+
+/**
+ * Base interface for all inputs which involve text editing.
+ */
+abstract class TextInputElementBase implements InputElementBase {
+  /// @domName HTMLInputElement.autocomplete
+  String autocomplete;
+
+  /// @domName HTMLInputElement.maxLength
+  int maxLength;
+
+  /// @domName HTMLInputElement.pattern
+  String pattern;
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.size
+  int size;
+
+  /// @domName HTMLInputElement.select
+  void select();
+
+  /// @domName HTMLInputElement.selectionDirection
+  String selectionDirection;
+
+  /// @domName HTMLInputElement.selectionEnd
+  int selectionEnd;
+
+  /// @domName HTMLInputElement.selectionStart
+  int selectionStart;
+
+  /// @domName HTMLInputElement.setSelectionRange
+  void setSelectionRange(int start, int end, [String direction]);
+}
+
+/**
+ * Similar to [TextInputElement], but on platforms where search is styled
+ * differently this will get the search style.
+ */
+abstract class SearchInputElement implements TextInputElementBase {
+  factory SearchInputElement() => new InputElement(type: 'search');
+
+  /// @domName HTMLInputElement.dirName;
+  String dirName;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * A basic text input editor control.
+ */
+abstract class TextInputElement implements TextInputElementBase {
+  factory TextInputElement() => new InputElement(type: 'text');
+
+  /// @domName HTMLInputElement.dirName;
+  String dirName;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * A control for editing an absolute URL.
+ */
+abstract class UrlInputElement implements TextInputElementBase {
+  factory UrlInputElement() => new InputElement(type: 'url');
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * Represents a control for editing a telephone number.
+ *
+ * This provides a single line of text with minimal formatting help since
+ * there is a wide variety of telephone numbers.
+ */
+abstract class TelephoneInputElement implements TextInputElementBase {
+  factory TelephoneInputElement() => new InputElement(type: 'tel');
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * An e-mail address or list of e-mail addresses.
+ */
+abstract class EmailInputElement implements TextInputElementBase {
+  factory EmailInputElement() => new InputElement(type: 'email');
+
+  /// @domName HTMLInputElement.autocomplete
+  String autocomplete;
+
+  /// @domName HTMLInputElement.autofocus
+  bool autofocus;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+
+  /// @domName HTMLInputElement.maxLength
+  int maxLength;
+
+  /// @domName HTMLInputElement.multiple;
+  bool multiple;
+
+  /// @domName HTMLInputElement.pattern
+  String pattern;
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.size
+  int size;
+}
+
+/**
+ * Text with no line breaks (sensitive information).
+ */
+abstract class PasswordInputElement implements TextInputElementBase {
+  factory PasswordInputElement() => new InputElement(type: 'password');
+}
+
+/**
+ * Base interface for all input element types which involve ranges.
+ */
+abstract class RangeInputElementBase implements InputElementBase {
+
+  /// @domName HTMLInputElement.list
+  Element get list;
+
+  /// @domName HTMLInputElement.max
+  String max;
+
+  /// @domName HTMLInputElement.min
+  String min;
+
+  /// @domName HTMLInputElement.step
+  String step;
+
+  /// @domName HTMLInputElement.valueAsNumber
+  num valueAsNumber;
+
+  /// @domName HTMLInputElement.stepDown
+  void stepDown([int n]);
+
+  /// @domName HTMLInputElement.stepUp
+  void stepUp([int n]);
+}
+
+/**
+ * A date and time (year, month, day, hour, minute, second, fraction of a
+ * second) with the time zone set to UTC.
+ */
+abstract class DateTimeInputElement implements RangeInputElementBase {
+  factory DateTimeInputElement() => new InputElement(type: 'datetime');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date (year, month, day) with no time zone.
+ */
+abstract class DateInputElement implements RangeInputElementBase {
+  factory DateInputElement() => new InputElement(type: 'date');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date consisting of a year and a month with no time zone.
+ */
+abstract class MonthInputElement implements RangeInputElementBase {
+  factory MonthInputElement() => new InputElement(type: 'month');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date consisting of a week-year number and a week number with no time zone.
+ */
+abstract class WeekInputElement implements RangeInputElementBase {
+  factory WeekInputElement() => new InputElement(type: 'week');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A time (hour, minute, seconds, fractional seconds) with no time zone.
+ */
+abstract class TimeInputElement implements RangeInputElementBase {
+  factory TimeInputElement() => new InputElement(type: 'time');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date and time (year, month, day, hour, minute, second, fraction of a
+ * second) with no time zone.
+ */
+abstract class LocalDateTimeInputElement implements RangeInputElementBase {
+  factory LocalDateTimeInputElement() =>
+      new InputElement(type: 'datetime-local');
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A numeric editor control.
+ */
+abstract class NumberInputElement implements RangeInputElementBase {
+  factory NumberInputElement() => new InputElement(type: 'number');
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * Similar to [NumberInputElement] but the browser may provide more optimal
+ * styling (such as a slider control).
+ */
+abstract class RangeInputElement implements RangeInputElementBase {
+  factory RangeInputElement() => new InputElement(type: 'range');
+}
+
+/**
+ * A boolean editor control.
+ *
+ * Note that if [indeterminate] is set then this control is in a third
+ * indeterminate state.
+ */
+abstract class CheckboxInputElement implements InputElementBase {
+  factory CheckboxInputElement() => new InputElement(type: 'checkbox');
+
+  /// @domName HTMLInputElement.checked
+  bool checked;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+
+/**
+ * A control that when used with other [ReadioButtonInputElement] controls
+ * forms a radio button group in which only one control can be checked at a
+ * time.
+ *
+ * Radio buttons are considered to be in the same radio button group if:
+ *
+ * * They are all of type 'radio'.
+ * * They all have either the same [FormElement] owner, or no owner.
+ * * Their name attributes contain the same name.
+ */
+abstract class RadioButtonInputElement implements InputElementBase {
+  factory RadioButtonInputElement() => new InputElement(type: 'radio');
+
+  /// @domName HTMLInputElement.checked
+  bool checked;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A control for picking files from the user's computer.
+ */
+abstract class FileUploadInputElement implements InputElementBase {
+  factory FileUploadInputElement() => new InputElement(type: 'file');
+
+  /// @domName HTMLInputElement.accept
+  String accept;
+
+  /// @domName HTMLInputElement.multiple
+  bool multiple;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.files
+  List<File> files;
+}
+
+/**
+ * A button, which when clicked, submits the form.
+ */
+abstract class SubmitButtonInputElement implements InputElementBase {
+  factory SubmitButtonInputElement() => new InputElement(type: 'submit');
+
+  /// @domName HTMLInputElement.formAction
+  String formAction;
+
+  /// @domName HTMLInputElement.formEnctype
+  String formEnctype;
+
+  /// @domName HTMLInputElement.formMethod
+  String formMethod;
+
+  /// @domName HTMLInputElement.formNoValidate
+  bool formNoValidate;
+
+  /// @domName HTMLInputElement.formTarget
+  String formTarget;
+}
+
+/**
+ * Either an image which the user can select a coordinate to or a form
+ * submit button.
+ */
+abstract class ImageButtonInputElement implements InputElementBase {
+  factory ImageButtonInputElement() => new InputElement(type: 'image');
+
+  /// @domName HTMLInputElement.alt
+  String alt;
+
+  /// @domName HTMLInputElement.formAction
+  String formAction;
+
+  /// @domName HTMLInputElement.formEnctype
+  String formEnctype;
+
+  /// @domName HTMLInputElement.formMethod
+  String formMethod;
+
+  /// @domName HTMLInputElement.formNoValidate
+  bool formNoValidate;
+
+  /// @domName HTMLInputElement.formTarget
+  String formTarget;
+
+  /// @domName HTMLInputElement.height
+  int height;
+
+  /// @domName HTMLInputElement.src
+  String src;
+
+  /// @domName HTMLInputElement.width
+  int width;
+}
+
+/**
+ * A button, which when clicked, resets the form.
+ */
+abstract class ResetButtonInputElement implements InputElementBase {
+  factory ResetButtonInputElement() => new InputElement(type: 'reset');
+}
+
+/**
+ * A button, with no default behavior.
+ */
+abstract class ButtonInputElement implements InputElementBase {
+  factory ButtonInputElement() => new InputElement(type: 'button');
+}
+
+
+/// @docsEditable true
 class InputElementEvents extends ElementEvents {
+  /// @docsEditable true
   InputElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get speechChange => this['webkitSpeechChange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -14353,153 +14994,228 @@
 
 }
 
+/// @docsEditable true
 class LocalWindowEvents extends Events {
+  /// @docsEditable true
   LocalWindowEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get beforeUnload => this['beforeunload'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get canPlay => this['canplay'];
 
+  /// @docsEditable true
   EventListenerList get canPlayThrough => this['canplaythrough'];
 
+  /// @docsEditable true
   EventListenerList get change => this['change'];
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get contextMenu => this['contextmenu'];
 
+  /// @docsEditable true
   EventListenerList get doubleClick => this['dblclick'];
 
+  /// @docsEditable true
   EventListenerList get deviceMotion => this['devicemotion'];
 
+  /// @docsEditable true
   EventListenerList get deviceOrientation => this['deviceorientation'];
 
+  /// @docsEditable true
   EventListenerList get drag => this['drag'];
 
+  /// @docsEditable true
   EventListenerList get dragEnd => this['dragend'];
 
+  /// @docsEditable true
   EventListenerList get dragEnter => this['dragenter'];
 
+  /// @docsEditable true
   EventListenerList get dragLeave => this['dragleave'];
 
+  /// @docsEditable true
   EventListenerList get dragOver => this['dragover'];
 
+  /// @docsEditable true
   EventListenerList get dragStart => this['dragstart'];
 
+  /// @docsEditable true
   EventListenerList get drop => this['drop'];
 
+  /// @docsEditable true
   EventListenerList get durationChange => this['durationchange'];
 
+  /// @docsEditable true
   EventListenerList get emptied => this['emptied'];
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get hashChange => this['hashchange'];
 
+  /// @docsEditable true
   EventListenerList get input => this['input'];
 
+  /// @docsEditable true
   EventListenerList get invalid => this['invalid'];
 
+  /// @docsEditable true
   EventListenerList get keyDown => this['keydown'];
 
+  /// @docsEditable true
   EventListenerList get keyPress => this['keypress'];
 
+  /// @docsEditable true
   EventListenerList get keyUp => this['keyup'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get loadedData => this['loadeddata'];
 
+  /// @docsEditable true
   EventListenerList get loadedMetadata => this['loadedmetadata'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get mouseDown => this['mousedown'];
 
+  /// @docsEditable true
   EventListenerList get mouseMove => this['mousemove'];
 
+  /// @docsEditable true
   EventListenerList get mouseOut => this['mouseout'];
 
+  /// @docsEditable true
   EventListenerList get mouseOver => this['mouseover'];
 
+  /// @docsEditable true
   EventListenerList get mouseUp => this['mouseup'];
 
+  /// @docsEditable true
   EventListenerList get mouseWheel => this['mousewheel'];
 
+  /// @docsEditable true
   EventListenerList get offline => this['offline'];
 
+  /// @docsEditable true
   EventListenerList get online => this['online'];
 
+  /// @docsEditable true
   EventListenerList get pageHide => this['pagehide'];
 
+  /// @docsEditable true
   EventListenerList get pageShow => this['pageshow'];
 
+  /// @docsEditable true
   EventListenerList get pause => this['pause'];
 
+  /// @docsEditable true
   EventListenerList get play => this['play'];
 
+  /// @docsEditable true
   EventListenerList get playing => this['playing'];
 
+  /// @docsEditable true
   EventListenerList get popState => this['popstate'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get rateChange => this['ratechange'];
 
+  /// @docsEditable true
   EventListenerList get reset => this['reset'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get scroll => this['scroll'];
 
+  /// @docsEditable true
   EventListenerList get search => this['search'];
 
+  /// @docsEditable true
   EventListenerList get seeked => this['seeked'];
 
+  /// @docsEditable true
   EventListenerList get seeking => this['seeking'];
 
+  /// @docsEditable true
   EventListenerList get select => this['select'];
 
+  /// @docsEditable true
   EventListenerList get stalled => this['stalled'];
 
+  /// @docsEditable true
   EventListenerList get storage => this['storage'];
 
+  /// @docsEditable true
   EventListenerList get submit => this['submit'];
 
+  /// @docsEditable true
   EventListenerList get suspend => this['suspend'];
 
+  /// @docsEditable true
   EventListenerList get timeUpdate => this['timeupdate'];
 
+  /// @docsEditable true
   EventListenerList get touchCancel => this['touchcancel'];
 
+  /// @docsEditable true
   EventListenerList get touchEnd => this['touchend'];
 
+  /// @docsEditable true
   EventListenerList get touchMove => this['touchmove'];
 
+  /// @docsEditable true
   EventListenerList get touchStart => this['touchstart'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 
+  /// @docsEditable true
   EventListenerList get volumeChange => this['volumechange'];
 
+  /// @docsEditable true
   EventListenerList get waiting => this['waiting'];
 
+  /// @docsEditable true
   EventListenerList get animationEnd => this['webkitAnimationEnd'];
 
+  /// @docsEditable true
   EventListenerList get animationIteration => this['webkitAnimationIteration'];
 
+  /// @docsEditable true
   EventListenerList get animationStart => this['webkitAnimationStart'];
 
+  /// @docsEditable true
   EventListenerList get transitionEnd => this['webkitTransitionEnd'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -15029,57 +15745,84 @@
 
 }
 
+/// @docsEditable true
 class MediaElementEvents extends ElementEvents {
+  /// @docsEditable true
   MediaElementEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get canPlay => this['canplay'];
 
+  /// @docsEditable true
   EventListenerList get canPlayThrough => this['canplaythrough'];
 
+  /// @docsEditable true
   EventListenerList get durationChange => this['durationchange'];
 
+  /// @docsEditable true
   EventListenerList get emptied => this['emptied'];
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 
+  /// @docsEditable true
   EventListenerList get loadedData => this['loadeddata'];
 
+  /// @docsEditable true
   EventListenerList get loadedMetadata => this['loadedmetadata'];
 
+  /// @docsEditable true
   EventListenerList get loadStart => this['loadstart'];
 
+  /// @docsEditable true
   EventListenerList get pause => this['pause'];
 
+  /// @docsEditable true
   EventListenerList get play => this['play'];
 
+  /// @docsEditable true
   EventListenerList get playing => this['playing'];
 
+  /// @docsEditable true
   EventListenerList get progress => this['progress'];
 
+  /// @docsEditable true
   EventListenerList get rateChange => this['ratechange'];
 
+  /// @docsEditable true
   EventListenerList get seeked => this['seeked'];
 
+  /// @docsEditable true
   EventListenerList get seeking => this['seeking'];
 
+  /// @docsEditable true
   EventListenerList get show => this['show'];
 
+  /// @docsEditable true
   EventListenerList get stalled => this['stalled'];
 
+  /// @docsEditable true
   EventListenerList get suspend => this['suspend'];
 
+  /// @docsEditable true
   EventListenerList get timeUpdate => this['timeupdate'];
 
+  /// @docsEditable true
   EventListenerList get volumeChange => this['volumechange'];
 
+  /// @docsEditable true
   EventListenerList get waiting => this['waiting'];
 
+  /// @docsEditable true
   EventListenerList get keyAdded => this['webkitkeyadded'];
 
+  /// @docsEditable true
   EventListenerList get keyError => this['webkitkeyerror'];
 
+  /// @docsEditable true
   EventListenerList get keyMessage => this['webkitkeymessage'];
 
+  /// @docsEditable true
   EventListenerList get needKey => this['webkitneedkey'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -15367,9 +16110,12 @@
 
 }
 
+/// @docsEditable true
 class MediaStreamEvents extends Events {
+  /// @docsEditable true
   MediaStreamEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -15443,13 +16189,18 @@
 
 }
 
+/// @docsEditable true
 class MediaStreamTrackEvents extends Events {
+  /// @docsEditable true
   MediaStreamTrackEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get ended => this['ended'];
 
+  /// @docsEditable true
   EventListenerList get mute => this['mute'];
 
+  /// @docsEditable true
   EventListenerList get unmute => this['unmute'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -15513,11 +16264,15 @@
 
 }
 
+/// @docsEditable true
 class MediaStreamTrackListEvents extends Events {
+  /// @docsEditable true
   MediaStreamTrackListEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addTrack => this['addtrack'];
 
+  /// @docsEditable true
   EventListenerList get removeTrack => this['removetrack'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -15663,9 +16418,12 @@
 
 }
 
+/// @docsEditable true
 class MessagePortEvents extends Events {
+  /// @docsEditable true
   MessagePortEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -16540,9 +17298,9 @@
   void remove() {
     // TODO(jacobr): should we throw an exception if parent is already null?
     // TODO(vsm): Use the native remove when available.
-    if (this.parent != null) {
-      final Node parent = this.parent;
-      parent.$dom_removeChild(this);
+    if (this.parentNode != null) {
+      final Node parent = this.parentNode;
+      parentNode.$dom_removeChild(this);
     }
   }
 
@@ -16552,7 +17310,7 @@
    */
   Node replaceWith(Node otherNode) {
     try {
-      final Node parent = this.parent;
+      final Node parent = this.parentNode;
       parent.$dom_replaceChild(otherNode, this);
     } catch (e) {
 
@@ -16635,8 +17393,12 @@
   Document get document native "Node_ownerDocument_Getter";
 
 
+  /** @domName Node.parentElement */
+  Element get parent native "Node_parentElement_Getter";
+
+
   /** @domName Node.parentNode */
-  Node get parent native "Node_parentNode_Getter";
+  Node get parentNode native "Node_parentNode_Getter";
 
 
   /** @domName Node.previousSibling */
@@ -17008,17 +17770,24 @@
 
 }
 
+/// @docsEditable true
 class NotificationEvents extends Events {
+  /// @docsEditable true
   NotificationEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get close => this['close'];
 
+  /// @docsEditable true
   EventListenerList get display => this['display'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get show => this['show'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -17782,17 +18551,24 @@
 
 }
 
+/// @docsEditable true
 class PeerConnection00Events extends Events {
+  /// @docsEditable true
   PeerConnection00Events(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addStream => this['addstream'];
 
+  /// @docsEditable true
   EventListenerList get connecting => this['connecting'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 
+  /// @docsEditable true
   EventListenerList get removeStream => this['removestream'];
 
+  /// @docsEditable true
   EventListenerList get stateChange => this['statechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -18559,15 +19335,21 @@
 
 }
 
+/// @docsEditable true
 class RtcDataChannelEvents extends Events {
+  /// @docsEditable true
   RtcDataChannelEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get close => this['close'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -18734,21 +19516,30 @@
 
 }
 
+/// @docsEditable true
 class RtcPeerConnectionEvents extends Events {
+  /// @docsEditable true
   RtcPeerConnectionEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addStream => this['addstream'];
 
+  /// @docsEditable true
   EventListenerList get iceCandidate => this['icecandidate'];
 
+  /// @docsEditable true
   EventListenerList get iceChange => this['icechange'];
 
+  /// @docsEditable true
   EventListenerList get negotiationNeeded => this['negotiationneeded'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 
+  /// @docsEditable true
   EventListenerList get removeStream => this['removestream'];
 
+  /// @docsEditable true
   EventListenerList get stateChange => this['statechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -19360,9 +20151,12 @@
 
 }
 
+/// @docsEditable true
 class SharedWorkerContextEvents extends WorkerContextEvents {
+  /// @docsEditable true
   SharedWorkerContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get connect => this['connect'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -19889,29 +20683,42 @@
 
 }
 
+/// @docsEditable true
 class SpeechRecognitionEvents extends Events {
+  /// @docsEditable true
   SpeechRecognitionEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get audioEnd => this['audioend'];
 
+  /// @docsEditable true
   EventListenerList get audioStart => this['audiostart'];
 
+  /// @docsEditable true
   EventListenerList get end => this['end'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get noMatch => this['nomatch'];
 
+  /// @docsEditable true
   EventListenerList get result => this['result'];
 
+  /// @docsEditable true
   EventListenerList get soundEnd => this['soundend'];
 
+  /// @docsEditable true
   EventListenerList get soundStart => this['soundstart'];
 
+  /// @docsEditable true
   EventListenerList get speechEnd => this['speechend'];
 
+  /// @docsEditable true
   EventListenerList get speechStart => this['speechstart'];
 
+  /// @docsEditable true
   EventListenerList get start => this['start'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -21408,9 +22215,12 @@
 
 }
 
+/// @docsEditable true
 class TextTrackEvents extends Events {
+  /// @docsEditable true
   TextTrackEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get cueChange => this['cuechange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -21541,11 +22351,15 @@
 
 }
 
+/// @docsEditable true
 class TextTrackCueEvents extends Events {
+  /// @docsEditable true
   TextTrackCueEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get enter => this['enter'];
 
+  /// @docsEditable true
   EventListenerList get exit => this['exit'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -21809,9 +22623,12 @@
 
 }
 
+/// @docsEditable true
 class TextTrackListEvents extends Events {
+  /// @docsEditable true
   TextTrackListEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get addTrack => this['addtrack'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -24805,15 +25622,21 @@
 
 }
 
+/// @docsEditable true
 class WebSocketEvents extends Events {
+  /// @docsEditable true
   WebSocketEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get close => this['close'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 
+  /// @docsEditable true
   EventListenerList get open => this['open'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -24878,9 +25701,12 @@
 
 }
 
+/// @docsEditable true
 class WorkerEvents extends AbstractWorkerEvents {
+  /// @docsEditable true
   WorkerEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get message => this['message'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -24984,9 +25810,12 @@
 
 }
 
+/// @docsEditable true
 class WorkerContextEvents extends Events {
+  /// @docsEditable true
   WorkerContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -27549,7 +28378,7 @@
   String _type;
 
   /** The element we are watching for events to happen on. */
-  Element _target;
+  EventTarget _target;
 
   // The distance to shift from upper case alphabet Roman letters to lower case.
   final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
@@ -27608,7 +28437,7 @@
    * General constructor, performs basic initialization for our improved
    * KeyboardEvent controller.
    */
-  _KeyboardEventController(Element target, String type) {
+  _KeyboardEventController(EventTarget target, String type) {
     _callbacks = [];
     _type = type;
     _target = target;
diff --git a/sdk/lib/html/docs/html_docs.json b/sdk/lib/html/docs/html_docs.json
index a88215d..de93b4a 100644
--- a/sdk/lib/html/docs/html_docs.json
+++ b/sdk/lib/html/docs/html_docs.json
@@ -205,19 +205,153 @@
   },
 "CanvasElement.dart":
   {
-
+  "  @JSName('toDataURL')":
+    [
+      "  /**",
+      "   * Returns a data URI containing a representation of the image in the ",
+      "   * format specified by type (defaults to 'image/png'). ",
+      "   * ",
+      "   * Data Uri format is as follow `data:[<MIME-type>][;charset=<encoding>][;base64],<data>`",
+      "   * ",
+      "   * Optional parameter [quality] in the range of 0.0 and 1.0 can be used when requesting [type]",
+      "   * 'image/jpeg' or 'image/webp'. If [quality] is not passed the default",
+      "   * value is used. Note: the default value varies by browser.",
+      "   * ",
+      "   * If the height or width of this canvas element is 0, then 'data:' is returned,",
+      "   * representing no data.",
+      "   * ",
+      "   * If the type requested is not 'image/png', and the returned value is ",
+      "   * 'data:image/png', then the requested type is not supported.",
+      "   * ",
+      "   * Example usage:",
+      "   * ",
+      "   *     CanvasElement canvas = new CanvasElement();",
+      "   *     var ctx = canvas.context2d",
+      "   *     ..fillStyle = \"rgb(200,0,0)\"",
+      "   *     ..fillRect(10, 10, 55, 50);",
+      "   *     var dataUrl = canvas.toDataURL(\"image/jpeg\", 0.95);",
+      "   *     // The Data Uri would look similar to",
+      "   *     // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA",
+      "   *     // AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO",
+      "   *     // 9TXL0Y4OHwAAAABJRU5ErkJggg=='",
+      "   *     //Create a new image element from the data URI.",
+      "   *     var img = new ImageElement();",
+      "   *     img.src = dataUrl;",
+      "   *     document.body.children.add(img);",
+      "   *     ",
+      "   * See also:",
+      "   * ",
+      "   * * [Data URI Scheme](http://en.wikipedia.org/wiki/Data_URI_scheme) from Wikipedia.",
+      "   * ",
+      "   * * [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/DOM/HTMLCanvasElement) from MDN.",
+      "   * ",
+      "   * * [toDataUrl](http://dev.w3.org/html5/spec/the-canvas-element.html#dom-canvas-todataurl) from W3C.",
+      "   */"
+    ],
+  "  int height;":
+    [
+      "  /// The height of this canvas element in CSS pixels."
+    ],
+  "  int width;":
+    [
+      "  /// The width of this canvas element in CSS pixels."
+    ]
   },
 "CanvasGradient.dart":
   {
-
+  "  void addColorStop(num offset, String color) native;":
+    [
+      "  /**",
+      "   * Adds a color stop to this gradient at the offset.",
+      "   *",
+      "   * The [offset] can range between 0.0 and 1.0.",
+      "   *",
+      "   * See also:",
+      "   *",
+      "   * * [Multiple Color Stops](https://developer.mozilla.org/en-US/docs/CSS/linear-gradient#Gradient_with_multiple_color_stops) from MDN.",
+      "   */"
+    ],
+  "class CanvasGradient native \"*CanvasGradient\" {":
+    [
+      "/**",
+      " * An opaque canvas object representing a gradient.",
+      " *",
+      " * Created by calling [createLinearGradient] or [createRadialGradient] on a",
+      " * [CanvasRenderingContext2D] object.",
+      " *",
+      " * Example usage:",
+      " *",
+      " *     var canvas = new CanvasElement(width: 600, height: 600);",
+      " *     var ctx = canvas.context2d;",
+      " *     ctx.clearRect(0, 0, 600, 600);",
+      " *     ctx.save();",
+      " *     // Create radial gradient.",
+      " *     CanvasGradient gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, 600);",
+      " *     gradient.addColorStop(0, '#000');",
+      " *     gradient.addColorStop(1, 'rgb(255, 255, 255)');",
+      " *     // Assign gradients to fill.",
+      " *     ctx.fillStyle = gradient;",
+      " *     // Draw a rectangle with a gradient fill.",
+      " *     ctx.fillRect(0, 0, 600, 600);",
+      " *     ctx.save();",
+      " *     document.body.children.add(canvas);",
+      " *",
+      " * See also:",
+      " *",
+      " * * [CanvasGradient](https://developer.mozilla.org/en-US/docs/DOM/CanvasGradient) from MDN.",
+      " * * [CanvasGradient](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasgradient) from whatwg.",
+      " * * [CanvasGradient](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvasgradient) from W3C.",
+      " */"
+    ]
   },
 "CanvasPattern.dart":
   {
-
+  "class CanvasPattern native \"*CanvasPattern\" {":
+    [
+      "/**",
+      " * An opaque object representing a pattern of image, canvas, or video.",
+      " *",
+      " * Created by calling [createPattern] on a [CanvasRenderingContext2D] object.",
+      " *",
+      " * Example usage:",
+      " *",
+      " *     var canvas = new CanvasElement(width: 600, height: 600);",
+      " *     var ctx = canvas.context2d;",
+      " *     var img = new ImageElement();",
+      " *     // Image src needs to be loaded before pattern is applied.",
+      " *     img.on.load.add((event) {",
+      " *       // When the image is loaded, create a pattern",
+      " *       // from the ImageElement.",
+      " *       CanvasPattern pattern = ctx.createPattern(img, 'repeat');",
+      " *       ctx.rect(0, 0, canvas.width, canvas.height);",
+      " *       ctx.fillStyle = pattern;",
+      " *       ctx.fill();",
+      " *     });",
+      " *     img.src = \"images/foo.jpg\";",
+      " *     document.body.children.add(canvas);",
+      " *",
+      " * See also:",
+      " * * [CanvasPattern](https://developer.mozilla.org/en-US/docs/DOM/CanvasPattern) from MDN.",
+      " * * [CanvasPattern](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvaspattern) from whatwg.",
+      " * * [CanvasPattern](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvaspattern) from W3C.",
+      " */"
+    ]
   },
 "CanvasRenderingContext.dart":
   {
-
+  "  final CanvasElement canvas;":
+    [
+      "  /// Reference to the canvas element to which this context belongs."
+    ],
+  "class CanvasRenderingContext native \"*CanvasRenderingContext\" {":
+    [
+      "/**",
+      " * A rendering context for a canvas element.",
+      " *",
+      " * This context is extended by [CanvasRenderingContext2D] and",
+      " * [WebGLRenderingContext].",
+      " */"
+    ]
   },
 "CanvasRenderingContext2D.dart":
   {
@@ -481,7 +615,7 @@
   },
 "DivElement.dart":
   {
-  "class DivElement extends Element implements Element native \"*HTMLDivElement\" {":
+  "class DivElement extends Element native \"*HTMLDivElement\" {":
     [
       "/**",
       " * Represents an HTML <div> element.",
@@ -508,63 +642,63 @@
   },
 "Document.dart":
   {
-  "  @Returns('_NodeList') @Creates('_NodeList')":
+  "  @JSName('querySelectorAll')":
     [
       "  /// Deprecated: use query(\"#$elementId\") instead."
     ],
-  "  Element $dom_createElement(String tagName) native \"createElement\";":
+  "  @JSName('createElement')":
     [
       "  /// Deprecated: use new Element.tag(tagName) instead."
     ],
-  "  Element $dom_elementFromPoint(int x, int y) native \"elementFromPoint\";":
+  "  @JSName('elementFromPoint')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  Element $dom_getElementById(String elementId) native \"getElementById\";":
+  "  @JSName('getElementById')":
     [
       "  /// Deprecated: use query(\"#$elementId\") instead."
     ],
-  "  Element $dom_querySelector(String selectors) native \"querySelector\";":
+  "  @JSName('querySelector')":
     [
       "  /// Deprecated: renamed to the shorter name [query]."
     ],
-  "  Element get $dom_webkitFullscreenElement => JS(\"Element\", \"#.webkitFullscreenElement\", this);":
+  "  @JSName('webkitFullscreenElement')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  Element get $dom_webkitPointerLockElement => JS(\"Element\", \"#.webkitPointerLockElement\", this);":
+  "  @JSName('webkitPointerLockElement')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  HeadElement get $dom_head => JS(\"HeadElement\", \"#.head\", this);":
+  "  @JSName('head')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  List<StyleSheet> get $dom_styleSheets => JS(\"_StyleSheetList\", \"#.styleSheets\", this);":
+  "  @JSName('styleSheets')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  Range $dom_caretRangeFromPoint(int x, int y) native \"caretRangeFromPoint\";":
+  "  @JSName('caretRangeFromPoint')":
     [
       "  /// Use the [Range] constructor instead."
     ],
-  "  String get $dom_lastModified => JS(\"String\", \"#.lastModified\", this);":
+  "  @JSName('lastModified')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  String get $dom_referrer => JS(\"String\", \"#.referrer\", this);":
+  "  @JSName('referrer')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  String get $dom_title => JS(\"String\", \"#.title\", this);":
+  "  @JSName('title')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  String get $dom_webkitVisibilityState => JS(\"String\", \"#.webkitVisibilityState\", this);":
+  "  @JSName('webkitVisibilityState')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  TouchList $dom_createTouchList() native \"createTouchList\";":
+  "  @JSName('createTouchList')":
     [
       "  /// Use the [TouchList] constructor isntead."
     ],
@@ -572,35 +706,35 @@
     [
       "  /// Returns the [Window] associated with the document."
     ],
-  "  bool get $dom_webkitFullscreenEnabled => JS(\"bool\", \"#.webkitFullscreenEnabled\", this);":
+  "  @JSName('webkitFullscreenEnabled')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  bool get $dom_webkitHidden => JS(\"bool\", \"#.webkitHidden\", this);":
+  "  @JSName('webkitHidden')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  bool get $dom_webkitIsFullScreen => JS(\"bool\", \"#.webkitIsFullScreen\", this);":
+  "  @JSName('webkitIsFullScreen')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  void $dom_webkitCancelFullScreen() native \"webkitCancelFullScreen\";":
+  "  @JSName('webkitCancelFullScreen')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  void $dom_webkitExitFullscreen() native \"webkitExitFullscreen\";":
+  "  @JSName('webkitExitFullscreen')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  void $dom_webkitExitPointerLock() native \"webkitExitPointerLock\";":
+  "  @JSName('webkitExitPointerLock')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  void set $dom_body(Element value) {":
+  "  @JSName('body')":
     [
       "  /// Moved to [HtmlDocument]."
     ],
-  "  void set $dom_title(String value) {":
+  "  @JSName('title')":
     [
       "  /// Moved to [HtmlDocument]."
     ]
@@ -905,6 +1039,58 @@
       "   * [String]). `null` indicates request failure.",
       "   */"
     ],
+  "  EventListenerList get abort => this['abort'];":
+    [
+      "  /**",
+      "   * Event listeners to be notified when request has been aborted,",
+      "   * generally due to calling `httpRequest.abort()`.",
+      "   */"
+    ],
+  "  EventListenerList get error => this['error'];":
+    [
+      "  /**",
+      "   * Event listeners to be notified when a request has failed, such as when a",
+      "   * cross-domain error occurred or the file wasn't found on the server.",
+      "   */"
+    ],
+  "  EventListenerList get load => this['load'];":
+    [
+      "  /**",
+      "   * Event listeners to be notified once the request has completed",
+      "   * *successfully*.",
+      "   */"
+    ],
+  "  EventListenerList get loadEnd => this['loadend'];":
+    [
+      "  /**",
+      "   * Event listeners to be notified once the request has completed (on",
+      "   * either success or failure).",
+      "   */"
+    ],
+  "  EventListenerList get loadStart => this['loadstart'];":
+    [
+      "  /**",
+      "   * Event listeners to be notified when the request starts, once",
+      "   * `httpRequest.send()` has been called.",
+      "   */"
+    ],
+  "  EventListenerList get progress => this['progress'];":
+    [
+      "  /**",
+      "   * Event listeners to be notified when data for the request ",
+      "   * is being sent or loaded.",
+      "   *",
+      "   * Progress events are fired every 50ms or for every byte transmitted,",
+      "   * whichever is less frequent.",
+      "   */"
+    ],
+  "  EventListenerList get readyStateChange => this['readystatechange'];":
+    [
+      "  /**",
+      "   * Event listeners to be notified every time the [HttpRequest]",
+      "   * object's `readyState` changes values.",
+      "   */"
+    ],
   "  HttpRequestEvents get on =>":
     [
       "  /**",
@@ -1050,6 +1236,22 @@
   "  void setRequestHeader(String header, String value) native;":
     [
       "  /** Sets HTTP `header` to `value`. */"
+    ],
+  "class HttpRequestEvents extends Events {":
+    [
+      "/**",
+      " * A class that supports listening for and dispatching events that can fire when",
+      " * making an HTTP request. ",
+      " *  ",
+      " * Here's an example of adding an event handler that executes once an HTTP",
+      " * request has fully loaded:",
+      " * ",
+      " *     httpRequest.on.loadEnd.add((e) => myCustomLoadEndHandler(e));",
+      " *",
+      " * Each property of this class is a read-only pointer to an [EventListenerList].",
+      " * That list holds all of the [EventListener]s that have registered for that",
+      " * particular type of event that fires from an HttpRequest.",
+      " */"
     ]
   },
 "HttpRequestException.dart":
@@ -1286,7 +1488,7 @@
   },
 "MenuElement.dart":
   {
-  "class MenuElement extends Element implements Element native \"*HTMLMenuElement\" {":
+  "class MenuElement extends Element native \"*HTMLMenuElement\" {":
     [
       "/**",
       " * An HTML <menu> element.",
@@ -2156,4 +2358,4 @@
   {
 
   }
-}
\ No newline at end of file
+}
diff --git a/sdk/lib/html/html_common/filtered_element_list.dart b/sdk/lib/html/html_common/filtered_element_list.dart
index b12ffdb..7486555 100644
--- a/sdk/lib/html/html_common/filtered_element_list.dart
+++ b/sdk/lib/html/html_common/filtered_element_list.dart
@@ -4,10 +4,22 @@
 
 part of html_common;
 
+/**
+ * An indexable collection of a node's descendants in the document tree,
+ * filtered so that only elements are in the collection.
+ */
 class FilteredElementList implements List {
   final Node _node;
   final List<Node> _childNodes;
 
+  /**
+   * Creates a collection of the elements that descend from a node.
+   *
+   * Example usage:
+   *
+   *     var filteredElements = new FilteredElementList(query("#container"));
+   *     // filteredElements is [a, b, c].
+   */
   FilteredElementList(Node node): _childNodes = node.nodes, _node = node;
 
   // We can't memoize this, since it's possible that children will be messed
diff --git a/sdk/lib/html/html_common/html_common.dart b/sdk/lib/html/html_common/html_common.dart
index 19d283a..18c63a9 100644
--- a/sdk/lib/html/html_common/html_common.dart
+++ b/sdk/lib/html/html_common/html_common.dart
@@ -9,3 +9,7 @@
 
 part 'filtered_element_list.dart';
 part 'lists.dart';
+
+// For annotating deprecated APIs.
+// TODO: remove once @deprecated is added to dart core.
+const deprecated = 0;
diff --git a/sdk/lib/html/html_common/html_common_dart2js.dart b/sdk/lib/html/html_common/html_common_dart2js.dart
index 53761f6..559f983 100644
--- a/sdk/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk/lib/html/html_common/html_common_dart2js.dart
@@ -10,3 +10,7 @@
 part 'conversions.dart';
 part 'filtered_element_list.dart';
 part 'lists.dart';
+
+// For annotating deprecated APIs.
+// TODO: remove once @deprecated is added to dart core.
+const deprecated = 0;
diff --git a/sdk/lib/html/idl/dart/dart.idl b/sdk/lib/html/idl/dart/dart.idl
index 1c97468..74f7e96 100644
--- a/sdk/lib/html/idl/dart/dart.idl
+++ b/sdk/lib/html/idl/dart/dart.idl
@@ -311,6 +311,9 @@
      // Provide missing constructor signature.
      Constructor([Optional] in HTMLFormElement form)]
     interface DOMFormData {
+      [Suppressed] void append(in DOMString name, in DOMString value, in DOMString filename);
+      [Custom] void append(in DOMString name, in DOMString value);
+      [Custom] void append(in DOMString name, in Blob value, [Optional] in DOMString filename);
     };
 }
 
diff --git a/sdk/lib/html/scripts/htmleventgenerator.py b/sdk/lib/html/scripts/htmleventgenerator.py
index 2489d12..a99f8de 100644
--- a/sdk/lib/html/scripts/htmleventgenerator.py
+++ b/sdk/lib/html/scripts/htmleventgenerator.py
@@ -221,7 +221,9 @@
     template_file = 'impl_%s.darttemplate' % events_class_name
     template = (self._template_loader.TryLoad(template_file) or
         '\n'
+        '/// @docsEditable true\n'
         'class $CLASSNAME extends $SUPER {\n'
+        '  /// @docsEditable true\n'
         '  $CLASSNAME(EventTarget _ptr) : super(_ptr);\n'
         '$!MEMBERS}\n')
 
@@ -248,6 +250,7 @@
       if not full_event_name in custom_events:
         implementation_events_members.Emit(
             "\n"
+            "  /// @docsEditable true\n"
             "  EventListenerList get $NAME => this['$DOM_NAME'];\n",
           NAME=html_name,
             DOM_NAME=dom_name)
diff --git a/sdk/lib/html/scripts/htmlrenamer.py b/sdk/lib/html/scripts/htmlrenamer.py
index f6d01cb..89b8273 100644
--- a/sdk/lib/html/scripts/htmlrenamer.py
+++ b/sdk/lib/html/scripts/htmlrenamer.py
@@ -146,7 +146,7 @@
     'Node.cloneNode': 'clone',
     'Node.nextSibling': 'nextNode',
     'Node.ownerDocument': 'document',
-    'Node.parentNode': 'parent',
+    'Node.parentElement': 'parent',
     'Node.previousSibling': 'previousNode',
     'Node.textContent': 'text',
     'SvgElement.className': '$dom_svgClassName',
@@ -300,7 +300,6 @@
     "Node.get:DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC",
     "Node.get:NOTATION_NODE",
     "Node.normalize",
-    "Node.get:parentElement",
     "Node.get:ATTRIBUTE_NODE",
     "Node.get:ENTITY_NODE",
     "Node.get:DOCUMENT_POSITION_CONTAINED_BY",
diff --git a/sdk/lib/html/scripts/systemhtml.py b/sdk/lib/html/scripts/systemhtml.py
index c0041cb..3a7abb5 100644
--- a/sdk/lib/html/scripts/systemhtml.py
+++ b/sdk/lib/html/scripts/systemhtml.py
@@ -48,7 +48,7 @@
     'HTMLSelectElement.selectedOptions',
     'HTMLTableElement.createTBody',
     'IDBDatabase.transaction',
-    'KeyboardEvent.initKeyboardEvent',    
+    'KeyboardEvent.initKeyboardEvent',
     'MouseEvent.offsetX',
     'MouseEvent.offsetY',
     'Navigator.language',
@@ -363,7 +363,8 @@
     implements = self._backend.AdditionalImplementedInterfaces()
     for parent in self._interface.parents:
       parent_type_info = self._type_registry.TypeInfo(parent.type.id)
-      if parent_type_info != base_type_info:
+      if parent_type_info.interface_name() != base_class and \
+          parent_type_info != base_type_info:
         implements.append(parent_type_info.interface_name())
 
     secure_base_name = self._backend.SecureBaseName(interface_name)
diff --git a/sdk/lib/html/src/KeyboardEventController.dart b/sdk/lib/html/src/KeyboardEventController.dart
index 33e2f63..f949b32 100644
--- a/sdk/lib/html/src/KeyboardEventController.dart
+++ b/sdk/lib/html/src/KeyboardEventController.dart
@@ -32,7 +32,7 @@
   String _type;
 
   /** The element we are watching for events to happen on. */
-  Element _target;
+  EventTarget _target;
 
   // The distance to shift from upper case alphabet Roman letters to lower case.
   final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
@@ -91,7 +91,7 @@
    * General constructor, performs basic initialization for our improved
    * KeyboardEvent controller.
    */
-  _KeyboardEventController(Element target, String type) {
+  _KeyboardEventController(EventTarget target, String type) {
     _callbacks = [];
     _type = type;
     _target = target;
diff --git a/sdk/lib/html/templates/html/impl/impl_DocumentFragment.darttemplate b/sdk/lib/html/templates/html/impl/impl_DocumentFragment.darttemplate
index a164c0d..b9b8cdb 100644
--- a/sdk/lib/html/templates/html/impl/impl_DocumentFragment.darttemplate
+++ b/sdk/lib/html/templates/html/impl/impl_DocumentFragment.darttemplate
@@ -29,9 +29,11 @@
   factory $CLASSNAME.svg(String svgContent) =>
       _$(CLASSNAME)FactoryProvider.createDocumentFragment_svg(svgContent);
 
+  @deprecated
   List<Element> get elements => this.children;
 
   // TODO: The type of value should be Collection<Element>. See http://b/5392897
+  @deprecated
   void set elements(value) {
     this.children = value;
   }
@@ -139,12 +141,12 @@
   String get webkitdropzone => "";
   String get webkitRegionOverflow => "";
   Element get $m_firstElementChild {
-    if (elements.length > 0) {
-      return elements[0];
+    if (children.length > 0) {
+      return children[0];
     }
     return null;
   }
-  Element get $m_lastElementChild => elements.last;
+  Element get $m_lastElementChild => children.last;
   Element get nextElementSibling => null;
   Element get previousElementSibling => null;
   Element get offsetParent => null;
diff --git a/sdk/lib/html/templates/html/impl/impl_Element.darttemplate b/sdk/lib/html/templates/html/impl/impl_Element.darttemplate
index aab5f01..b253d2d 100644
--- a/sdk/lib/html/templates/html/impl/impl_Element.darttemplate
+++ b/sdk/lib/html/templates/html/impl/impl_Element.darttemplate
@@ -373,11 +373,14 @@
   /**
    * Deprecated, use innerHtml instead.
    */
+  @deprecated
   String get innerHTML => this.innerHtml;
+  @deprecated
   void set innerHTML(String value) {
     this.innerHtml = value;
   }
 
+  @deprecated
   void set elements(Collection<Element> value) {
     this.children = value;
   }
@@ -385,6 +388,7 @@
   /**
    * Deprecated, use [children] instead.
    */
+  @deprecated
   List<Element> get elements => this.children;
 
   /**
@@ -545,7 +549,7 @@
   void _insertAdjacentNode(String where, Node node) {
     switch (where.toLowerCase()) {
       case 'beforebegin':
-        this.parent.insertBefore(node, this);
+        this.parentNode.insertBefore(node, this);
         break;
       case 'afterbegin':
         var first = this.nodes.length > 0 ? this.nodes[0] : null;
@@ -555,7 +559,7 @@
         this.nodes.add(node);
         break;
       case 'afterend':
-        this.parent.insertBefore(node, this.nextNode);
+        this.parentNode.insertBefore(node, this.nextNode);
         break;
       default:
         throw new ArgumentError("Invalid position ${where}");
diff --git a/sdk/lib/html/templates/html/impl/impl_HTMLInputElement.darttemplate b/sdk/lib/html/templates/html/impl/impl_HTMLInputElement.darttemplate
new file mode 100644
index 0000000..a4c4e9a
--- /dev/null
+++ b/sdk/lib/html/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -0,0 +1,498 @@
+// 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.
+
+part of $LIBRARYNAME;
+
+/// @domName $DOMNAME
+class $CLASSNAME$EXTENDS implements
+    HiddenInputElement,
+    SearchInputElement,
+    TextInputElement,
+    UrlInputElement,
+    TelephoneInputElement,
+    EmailInputElement,
+    PasswordInputElement,
+    DateTimeInputElement,
+    DateInputElement,
+    MonthInputElement,
+    WeekInputElement,
+    TimeInputElement,
+    LocalDateTimeInputElement,
+    NumberInputElement,
+    RangeInputElement,
+    CheckboxInputElement,
+    RadioButtonInputElement,
+    FileUploadInputElement,
+    SubmitButtonInputElement,
+    ImageButtonInputElement,
+    ResetButtonInputElement,
+    ButtonInputElement
+    $NATIVESPEC {
+$!MEMBERS
+}
+
+
+// Interfaces representing the InputElement APIs which are supported
+// for the various types of InputElement.
+// From http://dev.w3.org/html5/spec/the-input-element.html#the-input-element.
+
+/**
+ * Exposes the functionality common between all InputElement types.
+ */
+abstract class InputElementBase implements Element {
+  /// @domName HTMLInputElement.autofocus
+  bool autofocus;
+
+  /// @domName HTMLInputElement.disabled
+  bool disabled;
+
+  /// @domName HTMLInputElement.incremental
+  bool incremental;
+
+  /// @domName HTMLInputElement.indeterminate
+  bool indeterminate;
+
+  /// @domName HTMLInputElement.labels
+  List<Node> get labels;
+
+  /// @domName HTMLInputElement.name
+  String name;
+
+  /// @domName HTMLInputElement.validationMessage
+  String get validationMessage;
+
+  /// @domName HTMLInputElement.validity
+  ValidityState get validity;
+
+  /// @domName HTMLInputElement.value
+  String value;
+
+  /// @domName HTMLInputElement.willValidate
+  bool get willValidate;
+
+  /// @domName HTMLInputElement.checkValidity
+  bool checkValidity();
+
+  /// @domName HTMLInputElement.setCustomValidity
+  void setCustomValidity(String error);
+}
+
+/**
+ * Hidden input which is not intended to be seen or edited by the user.
+ */
+abstract class HiddenInputElement implements Element {
+  factory HiddenInputElement() => new InputElement(type: 'hidden');
+}
+
+
+/**
+ * Base interface for all inputs which involve text editing.
+ */
+abstract class TextInputElementBase implements InputElementBase {
+  /// @domName HTMLInputElement.autocomplete
+  String autocomplete;
+
+  /// @domName HTMLInputElement.maxLength
+  int maxLength;
+
+  /// @domName HTMLInputElement.pattern
+  String pattern;
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.size
+  int size;
+
+  /// @domName HTMLInputElement.select
+  void select();
+
+  /// @domName HTMLInputElement.selectionDirection
+  String selectionDirection;
+
+  /// @domName HTMLInputElement.selectionEnd
+  int selectionEnd;
+
+  /// @domName HTMLInputElement.selectionStart
+  int selectionStart;
+
+  /// @domName HTMLInputElement.setSelectionRange
+  void setSelectionRange(int start, int end, [String direction]);
+}
+
+/**
+ * Similar to [TextInputElement], but on platforms where search is styled
+ * differently this will get the search style.
+ */
+abstract class SearchInputElement implements TextInputElementBase {
+  factory SearchInputElement() => new InputElement(type: 'search');
+
+  /// @domName HTMLInputElement.dirName;
+  String dirName;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * A basic text input editor control.
+ */
+abstract class TextInputElement implements TextInputElementBase {
+  factory TextInputElement() => new InputElement(type: 'text');
+
+  /// @domName HTMLInputElement.dirName;
+  String dirName;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * A control for editing an absolute URL.
+ */
+abstract class UrlInputElement implements TextInputElementBase {
+  factory UrlInputElement() => new InputElement(type: 'url');
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * Represents a control for editing a telephone number.
+ *
+ * This provides a single line of text with minimal formatting help since
+ * there is a wide variety of telephone numbers.
+ */
+abstract class TelephoneInputElement implements TextInputElementBase {
+  factory TelephoneInputElement() => new InputElement(type: 'tel');
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+}
+
+/**
+ * An e-mail address or list of e-mail addresses.
+ */
+abstract class EmailInputElement implements TextInputElementBase {
+  factory EmailInputElement() => new InputElement(type: 'email');
+
+  /// @domName HTMLInputElement.autocomplete
+  String autocomplete;
+
+  /// @domName HTMLInputElement.autofocus
+  bool autofocus;
+
+  /// @domName HTMLInputElement.list;
+  Element get list;
+
+  /// @domName HTMLInputElement.maxLength
+  int maxLength;
+
+  /// @domName HTMLInputElement.multiple;
+  bool multiple;
+
+  /// @domName HTMLInputElement.pattern
+  String pattern;
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.size
+  int size;
+}
+
+/**
+ * Text with no line breaks (sensitive information).
+ */
+abstract class PasswordInputElement implements TextInputElementBase {
+  factory PasswordInputElement() => new InputElement(type: 'password');
+}
+
+/**
+ * Base interface for all input element types which involve ranges.
+ */
+abstract class RangeInputElementBase implements InputElementBase {
+
+  /// @domName HTMLInputElement.list
+  Element get list;
+
+  /// @domName HTMLInputElement.max
+  String max;
+
+  /// @domName HTMLInputElement.min
+  String min;
+
+  /// @domName HTMLInputElement.step
+  String step;
+
+  /// @domName HTMLInputElement.valueAsNumber
+  num valueAsNumber;
+
+  /// @domName HTMLInputElement.stepDown
+  void stepDown([int n]);
+
+  /// @domName HTMLInputElement.stepUp
+  void stepUp([int n]);
+}
+
+/**
+ * A date and time (year, month, day, hour, minute, second, fraction of a
+ * second) with the time zone set to UTC.
+ */
+abstract class DateTimeInputElement implements RangeInputElementBase {
+  factory DateTimeInputElement() => new InputElement(type: 'datetime');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date (year, month, day) with no time zone.
+ */
+abstract class DateInputElement implements RangeInputElementBase {
+  factory DateInputElement() => new InputElement(type: 'date');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date consisting of a year and a month with no time zone.
+ */
+abstract class MonthInputElement implements RangeInputElementBase {
+  factory MonthInputElement() => new InputElement(type: 'month');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date consisting of a week-year number and a week number with no time zone.
+ */
+abstract class WeekInputElement implements RangeInputElementBase {
+  factory WeekInputElement() => new InputElement(type: 'week');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A time (hour, minute, seconds, fractional seconds) with no time zone.
+ */
+abstract class TimeInputElement implements RangeInputElementBase {
+  factory TimeInputElement() => new InputElement(type: 'time');
+
+  /// @domName HTMLInputElement.valueAsDate
+  Date valueAsDate;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A date and time (year, month, day, hour, minute, second, fraction of a
+ * second) with no time zone.
+ */
+abstract class LocalDateTimeInputElement implements RangeInputElementBase {
+  factory LocalDateTimeInputElement() =>
+      new InputElement(type: 'datetime-local');
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A numeric editor control.
+ */
+abstract class NumberInputElement implements RangeInputElementBase {
+  factory NumberInputElement() => new InputElement(type: 'number');
+
+  /// @domName HTMLInputElement.placeholder
+  String placeholder;
+
+  /// @domName HTMLInputElement.readOnly
+  bool readOnly;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * Similar to [NumberInputElement] but the browser may provide more optimal
+ * styling (such as a slider control).
+ */
+abstract class RangeInputElement implements RangeInputElementBase {
+  factory RangeInputElement() => new InputElement(type: 'range');
+}
+
+/**
+ * A boolean editor control.
+ *
+ * Note that if [indeterminate] is set then this control is in a third
+ * indeterminate state.
+ */
+abstract class CheckboxInputElement implements InputElementBase {
+  factory CheckboxInputElement() => new InputElement(type: 'checkbox');
+
+  /// @domName HTMLInputElement.checked
+  bool checked;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+
+/**
+ * A control that when used with other [ReadioButtonInputElement] controls
+ * forms a radio button group in which only one control can be checked at a
+ * time.
+ *
+ * Radio buttons are considered to be in the same radio button group if:
+ *
+ * * They are all of type 'radio'.
+ * * They all have either the same [FormElement] owner, or no owner.
+ * * Their name attributes contain the same name.
+ */
+abstract class RadioButtonInputElement implements InputElementBase {
+  factory RadioButtonInputElement() => new InputElement(type: 'radio');
+
+  /// @domName HTMLInputElement.checked
+  bool checked;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+}
+
+/**
+ * A control for picking files from the user's computer.
+ */
+abstract class FileUploadInputElement implements InputElementBase {
+  factory FileUploadInputElement() => new InputElement(type: 'file');
+
+  /// @domName HTMLInputElement.accept
+  String accept;
+
+  /// @domName HTMLInputElement.multiple
+  bool multiple;
+
+  /// @domName HTMLInputElement.required
+  bool required;
+
+  /// @domName HTMLInputElement.files
+  List<File> files;
+}
+
+/**
+ * A button, which when clicked, submits the form.
+ */
+abstract class SubmitButtonInputElement implements InputElementBase {
+  factory SubmitButtonInputElement() => new InputElement(type: 'submit');
+
+  /// @domName HTMLInputElement.formAction
+  String formAction;
+
+  /// @domName HTMLInputElement.formEnctype
+  String formEnctype;
+
+  /// @domName HTMLInputElement.formMethod
+  String formMethod;
+
+  /// @domName HTMLInputElement.formNoValidate
+  bool formNoValidate;
+
+  /// @domName HTMLInputElement.formTarget
+  String formTarget;
+}
+
+/**
+ * Either an image which the user can select a coordinate to or a form
+ * submit button.
+ */
+abstract class ImageButtonInputElement implements InputElementBase {
+  factory ImageButtonInputElement() => new InputElement(type: 'image');
+
+  /// @domName HTMLInputElement.alt
+  String alt;
+
+  /// @domName HTMLInputElement.formAction
+  String formAction;
+
+  /// @domName HTMLInputElement.formEnctype
+  String formEnctype;
+
+  /// @domName HTMLInputElement.formMethod
+  String formMethod;
+
+  /// @domName HTMLInputElement.formNoValidate
+  bool formNoValidate;
+
+  /// @domName HTMLInputElement.formTarget
+  String formTarget;
+
+  /// @domName HTMLInputElement.height
+  int height;
+
+  /// @domName HTMLInputElement.src
+  String src;
+
+  /// @domName HTMLInputElement.width
+  int width;
+}
+
+/**
+ * A button, which when clicked, resets the form.
+ */
+abstract class ResetButtonInputElement implements InputElementBase {
+  factory ResetButtonInputElement() => new InputElement(type: 'reset');
+}
+
+/**
+ * A button, with no default behavior.
+ */
+abstract class ButtonInputElement implements InputElementBase {
+  factory ButtonInputElement() => new InputElement(type: 'button');
+}
+
diff --git a/sdk/lib/html/templates/html/impl/impl_Node.darttemplate b/sdk/lib/html/templates/html/impl/impl_Node.darttemplate
index 07e0609..85671be 100644
--- a/sdk/lib/html/templates/html/impl/impl_Node.darttemplate
+++ b/sdk/lib/html/templates/html/impl/impl_Node.darttemplate
@@ -153,9 +153,9 @@
   void remove() {
     // TODO(jacobr): should we throw an exception if parent is already null?
     // TODO(vsm): Use the native remove when available.
-    if (this.parent != null) {
-      final Node parent = this.parent;
-      parent.$dom_removeChild(this);
+    if (this.parentNode != null) {
+      final Node parent = this.parentNode;
+      parentNode.$dom_removeChild(this);
     }
   }
 
@@ -165,7 +165,7 @@
    */
   Node replaceWith(Node otherNode) {
     try {
-      final Node parent = this.parent;
+      final Node parent = this.parentNode;
       parent.$dom_replaceChild(otherNode, this);
     } catch (e) {
 
diff --git a/sdk/lib/html/templates/html/impl/impl_SVGElement.darttemplate b/sdk/lib/html/templates/html/impl/impl_SVGElement.darttemplate
index 6d8826a..ef3305d 100644
--- a/sdk/lib/html/templates/html/impl/impl_SVGElement.darttemplate
+++ b/sdk/lib/html/templates/html/impl/impl_SVGElement.darttemplate
@@ -46,8 +46,10 @@
     return _cssClassSet;
   }
 
+  @deprecated
   List<Element> get elements => new FilteredElementList(this);
 
+  @deprecated
   void set elements(Collection<Element> value) {
     final elements = this.elements;
     elements.clear();
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 30f6948..4d6beaf 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -301,13 +301,18 @@
 // can't handle that.  Move it back after dart2js is completely done.
 var _transaction_fn;  // Assigned one of the static methods.
 
+/// @docsEditable true
 class DatabaseEvents extends Events {
+  /// @docsEditable true
   DatabaseEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get versionChange => this['versionchange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -867,11 +872,15 @@
     new OpenDBRequestEvents(this);
 }
 
+/// @docsEditable true
 class OpenDBRequestEvents extends RequestEvents {
+  /// @docsEditable true
   OpenDBRequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get blocked => this['blocked'];
 
+  /// @docsEditable true
   EventListenerList get upgradeNeeded => this['upgradeneeded'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -924,11 +933,15 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class RequestEvents extends Events {
+  /// @docsEditable true
   RequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get success => this['success'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -977,13 +990,18 @@
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 }
 
+/// @docsEditable true
 class TransactionEvents extends Events {
+  /// @docsEditable true
   TransactionEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get complete => this['complete'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -1024,9 +1042,12 @@
     new VersionChangeRequestEvents(this);
 }
 
+/// @docsEditable true
 class VersionChangeRequestEvents extends RequestEvents {
+  /// @docsEditable true
   VersionChangeRequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get blocked => this['blocked'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 2043e5c..e01edb1 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -194,13 +194,18 @@
 
 }
 
+/// @docsEditable true
 class DatabaseEvents extends Events {
+  /// @docsEditable true
   DatabaseEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get versionChange => this['versionchange'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -784,11 +789,15 @@
 
 }
 
+/// @docsEditable true
 class OpenDBRequestEvents extends RequestEvents {
+  /// @docsEditable true
   OpenDBRequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get blocked => this['blocked'];
 
+  /// @docsEditable true
   EventListenerList get upgradeNeeded => this['upgradeneeded'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -848,11 +857,15 @@
 
 }
 
+/// @docsEditable true
 class RequestEvents extends Events {
+  /// @docsEditable true
   RequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get success => this['success'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -910,13 +923,18 @@
 
 }
 
+/// @docsEditable true
 class TransactionEvents extends Events {
+  /// @docsEditable true
   TransactionEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get complete => this['complete'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -972,9 +990,12 @@
 
 }
 
+/// @docsEditable true
 class VersionChangeRequestEvents extends RequestEvents {
+  /// @docsEditable true
   VersionChangeRequestEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get blocked => this['blocked'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index ecf7959..c24bedb 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -66,7 +66,7 @@
       }
     }
     if (future == null) {
-      return new Future.immedidate(-1);
+      return new Future.immediate(-1);
     } else {
       return future;
     }
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 5c8a2f0..24cb85b 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -889,7 +889,22 @@
 
   /**
    * Set this property to [:true:] if this connection should
-   * automatically follow redirects. The default is [:true:].
+   * automatically follow redirects. The default is
+   * [:true:].
+   *
+   * Automatic redirect will only happen for "GET" and "HEAD" requests
+   * and only for the status codes [:HttpStatus.MOVED_PERMANENTLY:]
+   * (301), [:HttpStatus.FOUND:] (302),
+   * [:HttpStatus.MOVED_TEMPORARILY:] (302, alias for
+   * [:HttpStatus.FOUND:]), [:HttpStatus.SEE_OTHER:] (303) and
+   * [:HttpStatus.TEMPORARY_REDIRECT:] (307). For
+   * [:HttpStatus.SEE_OTHER:] (303) autmatic redirect will also happen
+   * for "POST" requests with the method changed to "GET" when
+   * following the redirect.
+   *
+   * All headers added to the request will be added to the redirection
+   * request(s). However, any body send with the request will not be
+   * part of the redirection request(s).
    */
   bool followRedirects;
 
@@ -909,9 +924,13 @@
   /**
    * Redirect this connection to a new URL. The default value for
    * [method] is the method for the current request. The default value
-   * for [url] is the value of the [:HttpStatus.LOCATION:] header of
+   * for [url] is the value of the [:HttpHeaders.LOCATION:] header of
    * the current response. All body data must have been read from the
    * current response before calling [redirect].
+   *
+   * All headers added to the request will be added to the redirection
+   * request(s). However, any body send with the request will not be
+   * part of the redirection request(s).
    */
   void redirect([String method, Uri url]);
 
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 5672bb5..30fe2c1 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -832,7 +832,7 @@
   }
 
   bool _write(List<int> data, [bool copyBuffer = false]) {
-    if (_isRequestDone) {
+    if (_isRequestDone || !_hasBody || _httpParser.upgrade) {
       return _socket.outputStream.write(data, copyBuffer);
     } else {
       _bufferData(data, copyBuffer);
@@ -841,7 +841,7 @@
   }
 
   bool _writeFrom(List<int> data, [int offset, int len]) {
-    if (_isRequestDone) {
+    if (_isRequestDone || !_hasBody || _httpParser.upgrade) {
       return _socket.outputStream.writeFrom(data, offset, len);
     } else {
       if (offset == null) offset = 0;
@@ -895,7 +895,8 @@
   void _onRequestReceived(String method,
                           String uri,
                           String version,
-                          _HttpHeaders headers) {
+                          _HttpHeaders headers,
+                          bool hasBody) {
     _state = _HttpConnectionBase.ACTIVE;
     // Create new request and response objects for this request.
     _request = new _HttpRequest(this);
@@ -905,13 +906,16 @@
     _response._protocolVersion = version;
     _response._headResponse = method == "HEAD";
     _response.persistentConnection = _httpParser.persistentConnection;
+    _hasBody = hasBody;
     if (onRequestReceived != null) {
       onRequestReceived(_request, _response);
     }
+    _checkDone();
   }
 
   void _onDataReceived(List<int> data) {
     _request._onDataReceived(data);
+    _checkDone();
   }
 
   void _checkDone() {
@@ -933,7 +937,7 @@
       } else {
         _state = _HttpConnectionBase.IDLE;
       }
-    } else if (_isResponseDone) {
+    } else if (_isResponseDone && _hasBody) {
       // If the response is closed before the request is fully read
       // close this connection. If there is buffered output
       // (e.g. error response for invalid request where the server did
@@ -947,19 +951,20 @@
 
   void _onDataEnd(bool close) {
     // Start sending queued response if any.
-    _writeBufferedResponse();
     _state |= _HttpConnectionBase.REQUEST_DONE;
+    _writeBufferedResponse();
     _request._onDataEnd();
+    _checkDone();
   }
 
   void _responseClosed() {
     _state |= _HttpConnectionBase.RESPONSE_DONE;
-    _checkDone();
   }
 
   HttpServer _server;
   HttpRequest _request;
   HttpResponse _response;
+  bool _hasBody = false;
 
   // Buffer for data written before full response has been processed.
   _BufferList _buffer;
@@ -1286,10 +1291,16 @@
   String get reasonPhrase => _reasonPhrase;
 
   bool get isRedirect {
-    return statusCode == HttpStatus.MOVED_PERMANENTLY ||
-           statusCode == HttpStatus.FOUND ||
-           statusCode == HttpStatus.SEE_OTHER ||
-           statusCode == HttpStatus.TEMPORARY_REDIRECT;
+    var method = _connection._request._method;
+    if (method == "GET" || method == "HEAD") {
+      return statusCode == HttpStatus.MOVED_PERMANENTLY ||
+             statusCode == HttpStatus.FOUND ||
+             statusCode == HttpStatus.SEE_OTHER ||
+             statusCode == HttpStatus.TEMPORARY_REDIRECT;
+    } else if (method == "POST") {
+      return statusCode == HttpStatus.SEE_OTHER;
+    }
+    return false;
   }
 
   List<Cookie> get cookies {
@@ -1314,7 +1325,8 @@
   void _onResponseReceived(int statusCode,
                            String reasonPhrase,
                            String version,
-                           _HttpHeaders headers) {
+                           _HttpHeaders headers,
+                           bool hasBody) {
     _statusCode = statusCode;
     _reasonPhrase = reasonPhrase;
     _headers = headers;
@@ -1324,7 +1336,6 @@
     // Prepare for receiving data.
     _headers._mutable = false;
     _buffer = new _BufferList();
-
     if (isRedirect && _connection.followRedirects) {
       if (_connection._redirects == null ||
           _connection._redirects.length < _connection.maxRedirects) {
@@ -1346,7 +1357,12 @@
         }
         // Drain body and redirect.
         inputStream.onData = inputStream.read;
-        _connection.redirect();
+        if (_statusCode == HttpStatus.SEE_OTHER &&
+            _connection._method == "POST") {
+          _connection.redirect("GET");
+        } else {
+          _connection.redirect();
+        }
       } else {
         throw new RedirectLimitExceededException(_connection._redirects);
       }
@@ -1615,8 +1631,10 @@
   void _onResponseReceived(int statusCode,
                            String reasonPhrase,
                            String version,
-                           _HttpHeaders headers) {
-    _response._onResponseReceived(statusCode, reasonPhrase, version, headers);
+                           _HttpHeaders headers,
+                           bool hasBody) {
+    _response._onResponseReceived(
+        statusCode, reasonPhrase, version, headers, hasBody);
   }
 
   void _onDataReceived(List<int> data) {
@@ -2268,7 +2286,7 @@
 
   void authorize(_Credentials credentials, HttpClientRequest request) {
     // TODO(sgjesse): Implement!!!
-    throw new UnsupportedOperationException();
+    throw new UnsupportedError("Digest authentication not yet supported");
   }
 
   String username;
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 9dd569b..fbbd43d 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -326,13 +326,10 @@
           case _State.RESPONSE_LINE_ENDING:
             _expect(byte, _CharCode.LF);
             _messageType == _MessageType.RESPONSE;
-             _statusCode = parseInt(new String.fromCharCodes(_method_or_status_code));
+             _statusCode = parseInt(
+                 new String.fromCharCodes(_method_or_status_code));
             if (_statusCode < 100 || _statusCode > 599) {
               throw new HttpParserException("Invalid response status code");
-            } else {
-              // Check whether this response will never have a body.
-              _noMessageBody =
-                  _statusCode <= 199 || _statusCode == 204 || _statusCode == 304;
             }
             _state = _State.HEADER_START;
             break;
@@ -443,34 +440,37 @@
             if (_connectionUpgrade) {
               _state = _State.UPGRADED;
             }
+            var noBody;
             if (_requestParser) {
+              noBody = _contentLength == 0;
               requestStart(new String.fromCharCodes(_method_or_status_code),
                            new String.fromCharCodes(_uri_or_reason_phrase),
                            version,
-                           _headers);
+                           _headers,
+                           !noBody);
             } else {
+              // Check whether this response will never have a body.
+              noBody = _contentLength == 0 ||
+                       _statusCode <= 199 ||
+                       _statusCode == HttpStatus.NO_CONTENT ||
+                       _statusCode == HttpStatus.NOT_MODIFIED ||
+                       _responseToMethod == "HEAD";
               responseStart(_statusCode,
                             new String.fromCharCodes(_uri_or_reason_phrase),
                             version,
-                            _headers);
+                            _headers,
+                            !noBody);
             }
-            if (_state == _State.CANCELED) continue;
             _method_or_status_code.clear();
             _uri_or_reason_phrase.clear();
+            if (_state == _State.CANCELED) continue;
             if (!_connectionUpgrade) {
-              _method_or_status_code.clear();
-              _uri_or_reason_phrase.clear();
-              if (_chunked) {
+              if (noBody) {
+                _bodyEnd();
+                _reset();
+              } else if (_chunked) {
                 _state = _State.CHUNK_SIZE;
                 _remainingContent = 0;
-              } else if (_contentLength == 0 ||
-                         (_messageType == _MessageType.RESPONSE &&
-                          (_noMessageBody || _responseToMethod == "HEAD"))) {
-                // If there is no message body get ready to process the
-                // next request.
-                _bodyEnd();
-                if (_state == _State.CANCELED) continue;
-                _reset();
               } else if (_contentLength > 0) {
                 _remainingContent = _contentLength;
                 _state = _State.BODY;
@@ -691,7 +691,6 @@
     _connectionUpgrade = false;
     _chunked = false;
 
-    _noMessageBody = false;
     _responseToMethod = null;
     _remainingContent = null;
 
@@ -771,7 +770,6 @@
   bool _connectionUpgrade;
   bool _chunked;
 
-  bool _noMessageBody;
   String _responseToMethod;  // Indicates the method used for the request.
   int _remainingContent;
 
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index 7b0fbae..3900b61 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -29,6 +29,7 @@
 #source('file.dart');
 #source('file_impl.dart');
 #source('http.dart');
+#source('http_headers.dart');
 #source('http_impl.dart');
 #source('http_parser.dart');
 #source('http_session.dart');
diff --git a/sdk/lib/io/secure_server_socket.dart b/sdk/lib/io/secure_server_socket.dart
index 2ab290a..fb55196 100644
--- a/sdk/lib/io/secure_server_socket.dart
+++ b/sdk/lib/io/secure_server_socket.dart
@@ -13,24 +13,40 @@
    * the certificate, such as "CN=localhost" or "CN=myserver.mydomain.com".
    * The certificate is looked up in the NSS certificate database set by
    * SecureSocket.setCertificateDatabase.
+   *
+   * To request or require that clients authenticate by providing an SSL (TLS)
+   * client certificate, set the optional parameters requestClientCertificate or
+   * requireClientCertificate to true.  Require implies request, so one doesn't
+   * need to specify both.  To check whether a client certificate was received,
+   * check SecureSocket.peerCertificate after connecting.  If no certificate
+   * was received, the result will be null.
    */
   factory SecureServerSocket(String bindAddress,
-                          int port,
-                          int backlog,
-                          String certificate_name) =>
-      new _SecureServerSocket(bindAddress, port, backlog, certificate_name);
+                             int port,
+                             int backlog,
+                             String certificate_name,
+                             {bool requestClientCertificate: false,
+                              bool requireClientCertificate: false}) {
+    return new _SecureServerSocket(bindAddress,
+                                   port,
+                                   backlog,
+                                   certificate_name,
+                                   requestClientCertificate,
+                                   requireClientCertificate);
+  }
 }
 
 
 class _SecureServerSocket implements SecureServerSocket {
 
   _SecureServerSocket(String bindAddress,
-                   int port,
-                   int backlog,
-                   String certificate_name) {
-    _socket = new ServerSocket(bindAddress, port, backlog);
-    _socket.onConnection = this._onConnectionHandler;
-    _certificate_name = certificate_name;
+                      int port,
+                      int backlog,
+                      String this.certificate_name,
+                      bool this.requestClientCertificate,
+                      bool this.requireClientCertificate) {
+    socket = new ServerSocket(bindAddress, port, backlog);
+    socket.onConnection = this._onConnectionHandler;
   }
 
   void set onConnection(void callback(Socket connection)) {
@@ -38,19 +54,19 @@
   }
 
   void set onError(void callback(e)) {
-    _socket.onError = callback;
+    socket.onError = callback;
   }
 
   /**
    * Returns the port used by this socket.
    */
-  int get port => _socket.port;
+  int get port => socket.port;
 
   /**
    * Closes the socket.
    */
   void close() {
-    _socket.close();
+    socket.close();
   }
 
   void _onConnectionHandler(Socket connection) {
@@ -59,19 +75,25 @@
       throw new SocketIOException(
           "SecureServerSocket with no onConnection callback connected to");
     }
-    if (_certificate_name == null) {
+    if (certificate_name == null) {
       connection.close();
       throw new SocketIOException(
           "SecureServerSocket with server certificate not set connected to");
     }
-    var secure_connection = new _SecureSocket.server(connection.remoteHost,
-                                                  connection.remotePort,
-                                                  connection,
-                                                  _certificate_name);
+    var secure_connection = new _SecureSocket(
+        connection.remoteHost,
+        connection.remotePort,
+        certificate_name,
+        is_server: true,
+        socket: connection,
+        requestClientCertificate: requestClientCertificate,
+        requireClientCertificate: requireClientCertificate);
     _onConnectionCallback(secure_connection);
   }
 
-  ServerSocket _socket;
+  ServerSocket socket;
   var _onConnectionCallback;
-  String _certificate_name;
+  final String certificate_name;
+  final bool requestClientCertificate;
+  final bool requireClientCertificate;
 }
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 2721237..02742f7 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -11,9 +11,24 @@
   /**
    * Constructs a new secure client socket and connect it to the given
    * host on the given port. The returned socket is not yet connected
-   * but ready for registration of callbacks.
+   * but ready for registration of callbacks.  If sendClientCertificate is
+   * set to true, the socket will send a client certificate if one is
+   * requested by the server.  If clientCertificate is the nickname of
+   * a certificate in the certificate database, that certificate will be sent.
+   * If clientCertificate is null, which is the usual use case, an
+   * appropriate certificate will be searched for in the database and
+   * sent automatically, based on what the server says it will accept.
    */
-  factory SecureSocket(String host, int port) => new _SecureSocket(host, port);
+  factory SecureSocket(String host,
+                       int port,
+                       {bool sendClientCertificate: false,
+                        String certificateName}) {
+    return new _SecureSocket(host,
+                             port,
+                             certificateName,
+                             is_server: false,
+                             sendClientCertificate: sendClientCertificate);
+  }
 
   /**
    * Install a handler for unverifiable certificates.  The handler can inspect
@@ -23,6 +38,14 @@
    */
   void set onBadCertificate(bool callback(X509Certificate certificate));
 
+  /**
+   * Get the peerCertificate for a connected secure socket.  For a server
+   * socket, this will return the client certificate, or null, if no
+   * client certificate was received.  For a client socket, this
+   * will return the server's certificate.
+   */
+  X509Certificate get peerCertificate;
+
    /**
    * Initializes the NSS library with the path to a certificate database
    * containing root certificates for verifying certificate paths on
@@ -89,45 +112,61 @@
   static final int WRITE_ENCRYPTED = 3;
   static final int NUM_BUFFERS = 4;
 
-  int _count = 0;
-  // Constructs a new secure client socket.
-  factory _SecureSocket(String host, int port) =>
-      new _SecureSocket.internal(host, port, false);
-
-  // Constructs a new secure server socket, with the named server certificate.
-  factory _SecureSocket.server(String host,
-                            int port,
-                            Socket socket,
-                            String certificateName) =>
-      new _SecureSocket.internal(host, port, true, socket, certificateName);
-
-  _SecureSocket.internal(String host,
-                      int port,
-                      bool is_server,
-                      [Socket socket,
-                       String certificateName])
-      : _host = host,
-        _port = port,
-        _socket = socket,
-        _certificateName = certificateName,
-        _is_server = is_server,
-        _secureFilter = new _SecureFilter() {
-    if (_socket == null) {
-      _socket = new Socket(host, port);
+  _SecureSocket(String this.host,
+                int requestedPort,
+                String this.certificateName,
+                {bool this.is_server,
+                 Socket this.socket,
+                 bool this.requestClientCertificate: false,
+                 bool this.requireClientCertificate: false,
+                 bool this.sendClientCertificate: false})
+      : secureFilter = new _SecureFilter() {
+    // Throw an ArgumentError if any field is invalid.
+    _verifyFields();
+    if (socket == null) {
+      socket = new Socket(host, requestedPort);
     }
-    _socket.onConnect = _secureConnectHandler;
-    _socket.onData = _secureDataHandler;
-    _socket.onClosed = _secureCloseHandler;
-    _socket.onError = _secureErrorHandler;
-    _secureFilter.init();
-    _secureFilter.registerHandshakeCompleteCallback(_secureHandshakeCompleteHandler);
+    socket.onConnect = _secureConnectHandler;
+    socket.onData = _secureDataHandler;
+    socket.onClosed = _secureCloseHandler;
+    socket.onError = _secureErrorHandler;
+    secureFilter.init();
+    secureFilter.registerHandshakeCompleteCallback(
+        _secureHandshakeCompleteHandler);
   }
 
-  int get port => _socket.port;
+  void _verifyFields() {
+    if (host is! String) throw new ArgumentError(
+        "SecureSocket constructor: host is not a String");
+    assert(is_server is bool);
+    assert(socket == null || socket is Socket);
+    if (certificateName != null && certificateName is! String) {
+      throw new ArgumentError(
+          "SecureSocket constructor: certificateName is not null or a String");
+    }
+    if (certificateName == null && is_server) {
+      throw new ArgumentError(
+          "SecureSocket constructor: certificateName is null on a server");
+    }
+    if (requestClientCertificate is! bool) {
+      throw new ArgumentError(
+          "SecureSocket constructor: requestClientCertificate is not a bool");
+    }
+    if (requireClientCertificate is! bool) {
+      throw new ArgumentError(
+          "SecureSocket constructor: requireClientCertificate is not a bool");
+    }
+    if (sendClientCertificate is! bool) {
+      throw new ArgumentError(
+          "SecureSocket constructor: sendClientCertificate is not a bool");
+    }
+  }
 
-  String get remoteHost => _socket.remoteHost;
+  int get port => socket.port;
 
-  int get remotePort => _socket.remotePort;
+  String get remoteHost => socket.remoteHost;
+
+  int get remotePort => socket.remotePort;
 
   void set onClosed(void callback()) {
     if (_inputStream != null && callback != null) {
@@ -180,7 +219,7 @@
   void set _onWrite(void callback()) {
     _socketWriteHandler = callback;
     // Reset the one-shot onWrite handler.
-    _socket.onWrite = _secureWriteHandler;
+    socket.onWrite = _secureWriteHandler;
   }
 
   void set onBadCertificate(bool callback(X509Certificate certificate)) {
@@ -188,7 +227,7 @@
       throw new SocketIOException(
           "Callback provided to onBadCertificate is not a function or null");
     }
-    _secureFilter.registerBadCertificateCallback(callback);
+    secureFilter.registerBadCertificateCallback(callback);
   }
 
   InputStream get inputStream {
@@ -223,7 +262,7 @@
       _closedWrite = true;
       _writeEncryptedData();
       if (_filterWriteEmpty) {
-        _socket.close(true);
+        socket.close(true);
         _socketClosedWrite = true;
         if (_closedRead) {
           close(false);
@@ -232,11 +271,11 @@
     } else {
       _closedWrite = true;
       _closedRead = true;
-      _socket.close(false);
+      socket.close(false);
       _socketClosedWrite = true;
       _socketClosedRead = true;
-      _secureFilter.destroy();
-      _secureFilter = null;
+      secureFilter.destroy();
+      secureFilter = null;
       if (scheduledDataEvent != null) {
         scheduledDataEvent.cancel();
       }
@@ -253,7 +292,7 @@
     if (_status != CONNECTED) {
       return new List<int>(0);
     }
-    var buffer = _secureFilter.buffers[READ_PLAINTEXT];
+    var buffer = secureFilter.buffers[READ_PLAINTEXT];
     _readEncryptedData();
     int toRead = buffer.length;
     if (len != null) {
@@ -284,7 +323,7 @@
     }
 
     int bytesRead = 0;
-    var buffer = _secureFilter.buffers[READ_PLAINTEXT];
+    var buffer = secureFilter.buffers[READ_PLAINTEXT];
     // TODO(whesse): Currently this fails if the if is turned into a while loop.
     // Fix it so that it can loop and read more than one buffer's worth of data.
     if (bytes > bytesRead) {
@@ -310,7 +349,7 @@
       throw new SocketIOException("Writing to a closed socket");
     }
     if (_status != CONNECTED) return 0;
-    var buffer = _secureFilter.buffers[WRITE_PLAINTEXT];
+    var buffer = secureFilter.buffers[WRITE_PLAINTEXT];
     if (bytes > buffer.free) {
       bytes = buffer.free;
     }
@@ -322,9 +361,17 @@
     return bytes;
   }
 
+  X509Certificate get peerCertificate => secureFilter.peerCertificate;
+
   void _secureConnectHandler() {
     _connectPending = true;
-    _secureFilter.connect(_host, _port, _is_server, _certificateName);
+    secureFilter.connect(host,
+                         port,
+                         is_server,
+                         certificateName,
+                         requestClientCertificate || requireClientCertificate,
+                         requireClientCertificate,
+                         sendClientCertificate);
     _status = HANDSHAKE;
     _secureHandshake();
   }
@@ -338,7 +385,7 @@
       _secureHandshake();
     } else if (_status == CONNECTED &&
                _socketWriteHandler != null &&
-               _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
+               secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
       // We must be able to set onWrite from the onWrite callback.
       var handler = _socketWriteHandler;
       // Reset the one-shot handler.
@@ -420,10 +467,10 @@
 
   void _secureHandshake() {
     _readEncryptedData();
-    _secureFilter.handshake();
+    secureFilter.handshake();
     _writeEncryptedData();
-    if (_secureFilter.buffers[WRITE_ENCRYPTED].length > 0) {
-      _socket.onWrite = _secureWriteHandler;
+    if (secureFilter.buffers[WRITE_ENCRYPTED].length > 0) {
+      socket.onWrite = _secureWriteHandler;
     }
   }
 
@@ -434,7 +481,7 @@
       _socketConnectHandler();
     }
     if (_socketWriteHandler != null) {
-      _socket.onWrite = _secureWriteHandler;
+      socket.onWrite = _secureWriteHandler;
     }
   }
 
@@ -445,30 +492,30 @@
   void _readEncryptedData() {
     // Read from the socket, and push it through the filter as far as
     // possible.
-    var encrypted = _secureFilter.buffers[READ_ENCRYPTED];
-    var plaintext = _secureFilter.buffers[READ_PLAINTEXT];
+    var encrypted = secureFilter.buffers[READ_ENCRYPTED];
+    var plaintext = secureFilter.buffers[READ_PLAINTEXT];
     bool progress = true;
     while (progress) {
       progress = false;
       // Do not try to read plaintext from the filter while handshaking.
       if ((_status == CONNECTED) && plaintext.free > 0) {
-        int bytes = _secureFilter.processBuffer(READ_PLAINTEXT);
+        int bytes = secureFilter.processBuffer(READ_PLAINTEXT);
         if (bytes > 0) {
           plaintext.length += bytes;
           progress = true;
         }
       }
       if (encrypted.length > 0) {
-        int bytes = _secureFilter.processBuffer(READ_ENCRYPTED);
+        int bytes = secureFilter.processBuffer(READ_ENCRYPTED);
         if (bytes > 0) {
           encrypted.advanceStart(bytes);
           progress = true;
         }
       }
       if (!_socketClosedRead) {
-        int bytes = _socket.readList(encrypted.data,
-                                     encrypted.start + encrypted.length,
-                                     encrypted.free);
+        int bytes = socket.readList(encrypted.data,
+                                    encrypted.start + encrypted.length,
+                                    encrypted.free);
         if (bytes > 0) {
           encrypted.length += bytes;
           progress = true;
@@ -484,29 +531,29 @@
 
   void _writeEncryptedData() {
     if (_socketClosedWrite) return;
-    var encrypted = _secureFilter.buffers[WRITE_ENCRYPTED];
-    var plaintext = _secureFilter.buffers[WRITE_PLAINTEXT];
+    var encrypted = secureFilter.buffers[WRITE_ENCRYPTED];
+    var plaintext = secureFilter.buffers[WRITE_PLAINTEXT];
     while (true) {
       if (encrypted.length > 0) {
         // Write from the filter to the socket.
-        int bytes = _socket.writeList(encrypted.data,
-                                      encrypted.start,
-                                      encrypted.length);
+        int bytes = socket.writeList(encrypted.data,
+                                     encrypted.start,
+                                     encrypted.length);
         if (bytes == 0) {
           // The socket has blocked while we have data to write.
           // We must be notified when it becomes unblocked.
-          _socket.onWrite = _secureWriteHandler;
+          socket.onWrite = _secureWriteHandler;
           _filterWriteEmpty = false;
           break;
         }
         encrypted.advanceStart(bytes);
       } else {
-        var plaintext = _secureFilter.buffers[WRITE_PLAINTEXT];
+        var plaintext = secureFilter.buffers[WRITE_PLAINTEXT];
         if (plaintext.length > 0) {
-           int plaintext_bytes = _secureFilter.processBuffer(WRITE_PLAINTEXT);
+           int plaintext_bytes = secureFilter.processBuffer(WRITE_PLAINTEXT);
            plaintext.advanceStart(plaintext_bytes);
         }
-        int bytes = _secureFilter.processBuffer(WRITE_ENCRYPTED);
+        int bytes = secureFilter.processBuffer(WRITE_ENCRYPTED);
         if (bytes <= 0) {
           // We know the WRITE_ENCRYPTED buffer is empty, and the
           // filter wrote zero bytes to it, so the filter must be empty.
@@ -557,11 +604,13 @@
   bool get _socketClosed => _closedRead;
 
   // _SecureSocket cannot extend _Socket and use _Socket's factory constructor.
-  Socket _socket;
-  String _host;
-  int _port;
-  bool _is_server;
-  String _certificateName;
+  Socket socket;
+  final String host;
+  final bool is_server;
+  final String certificateName;
+  final bool requestClientCertificate;
+  final bool requireClientCertificate;
+  final bool sendClientCertificate;
 
   var _status = NOT_CONNECTED;
   bool _socketClosedRead = false;  // The network socket is closed for reading.
@@ -580,7 +629,7 @@
   Function _socketCloseHandler;
   Timer scheduledDataEvent;
 
-  _SecureFilter _secureFilter;
+  _SecureFilter secureFilter;
 }
 
 
@@ -611,10 +660,14 @@
   void connect(String hostName,
                int port,
                bool is_server,
-               String certificateName);
+               String certificateName,
+               bool requestClientCertificate,
+               bool requireClientCertificate,
+               bool sendClientCertificate);
   void destroy();
   void handshake();
   void init();
+  X509Certificate get peerCertificate;
   int processBuffer(int bufferIndex);
   void registerBadCertificateCallback(Function callback);
   void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index e080526..246fe31 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -14,44 +14,9 @@
 OutputStream _stderr;
 
 
-InputStream _getStdioInputStream() {
-  switch (_StdIOUtils._getStdioHandleType(0)) {
-    case _STDIO_HANDLE_TYPE_TERMINAL:
-    case _STDIO_HANDLE_TYPE_PIPE:
-    case _STDIO_HANDLE_TYPE_SOCKET:
-      Socket s = new _Socket._internalReadOnly();
-      _StdIOUtils._getStdioHandle(s, 0);
-      s._closed = false;
-      return s.inputStream;
-    case _STDIO_HANDLE_TYPE_FILE:
-      return new _FileInputStream.fromStdio(0);
-    default:
-      throw new FileIOException("Unsupported stdin type");
-  }
-}
-
-
-OutputStream _getStdioOutputStream(int fd) {
-  assert(fd == 1 || fd == 2);
-  switch (_StdIOUtils._getStdioHandleType(fd)) {
-    case _STDIO_HANDLE_TYPE_TERMINAL:
-    case _STDIO_HANDLE_TYPE_PIPE:
-    case _STDIO_HANDLE_TYPE_SOCKET:
-      Socket s = new _Socket._internalWriteOnly();
-      _StdIOUtils._getStdioHandle(s, fd);
-      s._closed = false;
-      return s.outputStream;
-    case _STDIO_HANDLE_TYPE_FILE:
-      return new _FileOutputStream.fromStdio(fd);
-    default:
-      throw new FileIOException("Unsupported stdin type");
-  }
-}
-
-
 InputStream get stdin {
   if (_stdin == null) {
-    _stdin = _getStdioInputStream();
+    _stdin = _StdIOUtils._getStdioInputStream();
   }
   return _stdin;
 }
@@ -59,7 +24,7 @@
 
 OutputStream get stdout {
   if (_stdout == null) {
-    _stdout = _getStdioOutputStream(1);
+    _stdout = _StdIOUtils._getStdioOutputStream(1);
   }
   return _stdout;
 }
@@ -67,13 +32,13 @@
 
 OutputStream get stderr {
   if (_stderr == null) {
-    _stderr = _getStdioOutputStream(2);
+    _stderr = _StdIOUtils._getStdioOutputStream(2);
   }
   return _stderr;
 }
 
 
 class _StdIOUtils {
-  external static _getStdioHandle(Socket socket, int num);
-  external static _getStdioHandleType(int num);
+  external static OutputStream _getStdioOutputStream(int fd);
+  external static InputStream _getStdioInputStream();
 }
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 1d0eb286..5d6f7d6 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -700,7 +700,6 @@
     if (!_isWebSocketUpgrade(response)) {
       _conn.detachSocket().socket.close();
       throw new WebSocketException("Protocol upgrade failed");
-      return;
     }
 
     // Connection upgrade successful.
diff --git a/sdk/lib/isolate/timer.dart b/sdk/lib/isolate/timer.dart
index d8da52f..1364239 100644
--- a/sdk/lib/isolate/timer.dart
+++ b/sdk/lib/isolate/timer.dart
@@ -5,45 +5,19 @@
 abstract class Timer {
   /**
    * Creates a new timer. The [callback] callback is invoked after
-   * [milliSeconds] milliseconds.
+   * [milliseconds] milliseconds.
    */
-  factory Timer(int milliSeconds, void callback(Timer timer)) {
-    if (_TimerFactory._factory == null) {
-      throw new UnsupportedError("Timer interface not supported.");
-    }
-    return _TimerFactory._factory(milliSeconds, callback, false);
-  }
+  external factory Timer(int milliseconds, void callback(Timer timer));
 
   /**
    * Creates a new repeating timer. The [callback] is invoked every
-   * [milliSeconds] millisecond until cancelled.
+   * [milliseconds] millisecond until cancelled.
    */
-  factory Timer.repeating(int milliSeconds, void callback(Timer timer)) {
-    if (_TimerFactory._factory == null) {
-      throw new UnsupportedError("Timer interface not supported.");
-    }
-    return _TimerFactory._factory(milliSeconds, callback, true);
-  }
+  external factory Timer.repeating(int milliseconds,
+                                   void callback(Timer timer));
 
   /**
    * Cancels the timer.
    */
   void cancel();
 }
-
-// TODO(ajohnsen): Patch timer once we have support for patching named
-//                 factory constructors in the VM.
-
-typedef Timer _TimerFactoryClosure(int milliSeconds,
-                                   void callback(Timer timer),
-                                   bool repeating);
-
-class _TimerFactory {
-  static _TimerFactoryClosure _factory;
-}
-
-// TODO(ahe): Warning: this is NOT called by Dartium. Instead, it sets
-// [_TimerFactory._factory] directly.
-void _setTimerFactoryClosure(_TimerFactoryClosure closure) {
-  _TimerFactory._factory = closure;
-}
diff --git a/sdk/lib/scalarlist/byte_arrays.dart b/sdk/lib/scalarlist/byte_arrays.dart
index 476cc46..df3ab98 100644
--- a/sdk/lib/scalarlist/byte_arrays.dart
+++ b/sdk/lib/scalarlist/byte_arrays.dart
@@ -369,7 +369,7 @@
    * not specified, it defaults to null, which indicates that the view extends
    * to the end of the byte array.
    */
-  external factory Int8List.view(ByteArray array, [int start, int length]);
+  external factory Int8List.view(ByteArray array, [int start = 0, int length]);
 }
 
 
@@ -393,7 +393,7 @@
    * not specified, it defaults to null, which indicates that the view extends
    * to the end of the byte array.
    */
-  external factory Uint8List.view(ByteArray array, [int start, int length]);
+  external factory Uint8List.view(ByteArray array, [int start = 0, int length]);
 }
 
 
@@ -419,7 +419,7 @@
    * extends to the end of the byte array.
    */
   external factory Uint8ClampedList.view(ByteArray array,
-                                         [int start, int length]);
+                                         [int start = 0, int length]);
 }
 
 
@@ -453,7 +453,7 @@
    * region does not contain an integral number of "int16s," or if it
    * is not "int16-aligned."
    */
-  external factory Int16List.view(ByteArray array, [int start, int length]);
+  external factory Int16List.view(ByteArray array, [int start = 0, int length]);
 }
 
 
@@ -487,7 +487,8 @@
    * region does not contain an integral number of "uint16s," or if it
    * is not "uint16-aligned."
    */
-  external factory Uint16List.view(ByteArray array, [int start, int length]);
+  external factory Uint16List.view(ByteArray array,
+                                   [int start = 0, int length]);
 }
 
 
@@ -521,7 +522,7 @@
    * region does not contain an integral number of "int32s," or if it
    * is not "int32-aligned."
    */
-  external factory Int32List.view(ByteArray array, [int start, int length]);
+  external factory Int32List.view(ByteArray array, [int start = 0, int length]);
 }
 
 
@@ -555,7 +556,8 @@
    * region does not contain an integral number of "uint32s," or if it
    * is not "uint32-aligned."
    */
-  external factory Uint32List.view(ByteArray array, [int start, int length]);
+  external factory Uint32List.view(ByteArray array,
+                                   [int start = 0, int length]);
 }
 
 
@@ -589,7 +591,7 @@
    * region does not contain an integral number of "int64s," or if it
    * is not "int64-aligned."
    */
-  external factory Int64List.view(ByteArray array, [int start, int length]);
+  external factory Int64List.view(ByteArray array, [int start = 0, int length]);
 }
 
 
@@ -623,7 +625,8 @@
    * region does not contain an integral number of "uint64s," or if it
    * is not "uint64-aligned."
    */
-  external factory Uint64List.view(ByteArray array, [int start, int length]);
+  external factory Uint64List.view(ByteArray array,
+                                   [int start = 0, int length]);
 }
 
 
@@ -658,7 +661,8 @@
    * region does not contain an integral number of "float32s," or if it
    * is not "float32-aligned."
    */
-  external factory Float32List.view(ByteArray array, [int start, int length]);
+  external factory Float32List.view(ByteArray array,
+                                    [int start = 0, int length]);
 }
 
 
@@ -693,5 +697,6 @@
    * region does not contain an integral number of "float64s," or if it
    * is not "float64-aligned."
    */
-  external factory Float64List.view(ByteArray array, [int start, int length]);
+  external factory Float64List.view(ByteArray array,
+                                    [int start = 0, int length]);
 }
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index 4a87d20..5ec3b6e 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -901,87 +901,129 @@
   final ElementInstance previousSibling;
 }
 
+/// @docsEditable true
 class ElementInstanceEvents extends Events {
+  /// @docsEditable true
   ElementInstanceEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get beforeCopy => this['beforecopy'];
 
+  /// @docsEditable true
   EventListenerList get beforeCut => this['beforecut'];
 
+  /// @docsEditable true
   EventListenerList get beforePaste => this['beforepaste'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get change => this['change'];
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get contextMenu => this['contextmenu'];
 
+  /// @docsEditable true
   EventListenerList get copy => this['copy'];
 
+  /// @docsEditable true
   EventListenerList get cut => this['cut'];
 
+  /// @docsEditable true
   EventListenerList get doubleClick => this['dblclick'];
 
+  /// @docsEditable true
   EventListenerList get drag => this['drag'];
 
+  /// @docsEditable true
   EventListenerList get dragEnd => this['dragend'];
 
+  /// @docsEditable true
   EventListenerList get dragEnter => this['dragenter'];
 
+  /// @docsEditable true
   EventListenerList get dragLeave => this['dragleave'];
 
+  /// @docsEditable true
   EventListenerList get dragOver => this['dragover'];
 
+  /// @docsEditable true
   EventListenerList get dragStart => this['dragstart'];
 
+  /// @docsEditable true
   EventListenerList get drop => this['drop'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get input => this['input'];
 
+  /// @docsEditable true
   EventListenerList get keyDown => this['keydown'];
 
+  /// @docsEditable true
   EventListenerList get keyPress => this['keypress'];
 
+  /// @docsEditable true
   EventListenerList get keyUp => this['keyup'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get mouseDown => this['mousedown'];
 
+  /// @docsEditable true
   EventListenerList get mouseMove => this['mousemove'];
 
+  /// @docsEditable true
   EventListenerList get mouseOut => this['mouseout'];
 
+  /// @docsEditable true
   EventListenerList get mouseOver => this['mouseover'];
 
+  /// @docsEditable true
   EventListenerList get mouseUp => this['mouseup'];
 
+  /// @docsEditable true
   EventListenerList get mouseWheel => this['mousewheel'];
 
+  /// @docsEditable true
   EventListenerList get paste => this['paste'];
 
+  /// @docsEditable true
   EventListenerList get reset => this['reset'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get scroll => this['scroll'];
 
+  /// @docsEditable true
   EventListenerList get search => this['search'];
 
+  /// @docsEditable true
   EventListenerList get select => this['select'];
 
+  /// @docsEditable true
   EventListenerList get selectStart => this['selectstart'];
 
+  /// @docsEditable true
   EventListenerList get submit => this['submit'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -4933,8 +4975,10 @@
     return _cssClassSet;
   }
 
+  @deprecated
   List<Element> get elements => new FilteredElementList(this);
 
+  @deprecated
   void set elements(Collection<Element> value) {
     final elements = this.elements;
     elements.clear();
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index 66b9d73..620d78b 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -1171,87 +1171,129 @@
 
 }
 
+/// @docsEditable true
 class ElementInstanceEvents extends Events {
+  /// @docsEditable true
   ElementInstanceEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get abort => this['abort'];
 
+  /// @docsEditable true
   EventListenerList get beforeCopy => this['beforecopy'];
 
+  /// @docsEditable true
   EventListenerList get beforeCut => this['beforecut'];
 
+  /// @docsEditable true
   EventListenerList get beforePaste => this['beforepaste'];
 
+  /// @docsEditable true
   EventListenerList get blur => this['blur'];
 
+  /// @docsEditable true
   EventListenerList get change => this['change'];
 
+  /// @docsEditable true
   EventListenerList get click => this['click'];
 
+  /// @docsEditable true
   EventListenerList get contextMenu => this['contextmenu'];
 
+  /// @docsEditable true
   EventListenerList get copy => this['copy'];
 
+  /// @docsEditable true
   EventListenerList get cut => this['cut'];
 
+  /// @docsEditable true
   EventListenerList get doubleClick => this['dblclick'];
 
+  /// @docsEditable true
   EventListenerList get drag => this['drag'];
 
+  /// @docsEditable true
   EventListenerList get dragEnd => this['dragend'];
 
+  /// @docsEditable true
   EventListenerList get dragEnter => this['dragenter'];
 
+  /// @docsEditable true
   EventListenerList get dragLeave => this['dragleave'];
 
+  /// @docsEditable true
   EventListenerList get dragOver => this['dragover'];
 
+  /// @docsEditable true
   EventListenerList get dragStart => this['dragstart'];
 
+  /// @docsEditable true
   EventListenerList get drop => this['drop'];
 
+  /// @docsEditable true
   EventListenerList get error => this['error'];
 
+  /// @docsEditable true
   EventListenerList get focus => this['focus'];
 
+  /// @docsEditable true
   EventListenerList get input => this['input'];
 
+  /// @docsEditable true
   EventListenerList get keyDown => this['keydown'];
 
+  /// @docsEditable true
   EventListenerList get keyPress => this['keypress'];
 
+  /// @docsEditable true
   EventListenerList get keyUp => this['keyup'];
 
+  /// @docsEditable true
   EventListenerList get load => this['load'];
 
+  /// @docsEditable true
   EventListenerList get mouseDown => this['mousedown'];
 
+  /// @docsEditable true
   EventListenerList get mouseMove => this['mousemove'];
 
+  /// @docsEditable true
   EventListenerList get mouseOut => this['mouseout'];
 
+  /// @docsEditable true
   EventListenerList get mouseOver => this['mouseover'];
 
+  /// @docsEditable true
   EventListenerList get mouseUp => this['mouseup'];
 
+  /// @docsEditable true
   EventListenerList get mouseWheel => this['mousewheel'];
 
+  /// @docsEditable true
   EventListenerList get paste => this['paste'];
 
+  /// @docsEditable true
   EventListenerList get reset => this['reset'];
 
+  /// @docsEditable true
   EventListenerList get resize => this['resize'];
 
+  /// @docsEditable true
   EventListenerList get scroll => this['scroll'];
 
+  /// @docsEditable true
   EventListenerList get search => this['search'];
 
+  /// @docsEditable true
   EventListenerList get select => this['select'];
 
+  /// @docsEditable true
   EventListenerList get selectStart => this['selectstart'];
 
+  /// @docsEditable true
   EventListenerList get submit => this['submit'];
 
+  /// @docsEditable true
   EventListenerList get unload => this['unload'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -6471,8 +6513,10 @@
     return _cssClassSet;
   }
 
+  @deprecated
   List<Element> get elements => new FilteredElementList(this);
 
+  @deprecated
   void set elements(Collection<Element> value) {
     final elements = this.elements;
     elements.clear();
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index dbaef00..b58d552 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -247,9 +247,12 @@
   }
 }
 
+/// @docsEditable true
 class AudioContextEvents extends Events {
+  /// @docsEditable true
   AudioContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get complete => this['complete'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -655,9 +658,12 @@
   final int bufferSize;
 }
 
+/// @docsEditable true
 class ScriptProcessorNodeEvents extends Events {
+  /// @docsEditable true
   ScriptProcessorNodeEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get audioProcess => this['audioprocess'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index ee711d3..d0b9b9e 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -387,9 +387,12 @@
 
 }
 
+/// @docsEditable true
 class AudioContextEvents extends Events {
+  /// @docsEditable true
   AudioContextEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get complete => this['complete'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -1015,9 +1018,12 @@
 
 }
 
+/// @docsEditable true
 class ScriptProcessorNodeEvents extends Events {
+  /// @docsEditable true
   ScriptProcessorNodeEvents(EventTarget _ptr) : super(_ptr);
 
+  /// @docsEditable true
   EventListenerList get audioProcess => this['audioprocess'];
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
diff --git a/tests/co19/co19-compiler.status b/tests/co19/co19-compiler.status
index 6a88581..b8c6535 100644
--- a/tests/co19/co19-compiler.status
+++ b/tests/co19/co19-compiler.status
@@ -73,7 +73,48 @@
 Language/13_Libraries_and_Scripts/1_Imports_A02_t16: Fail, OK
 Language/13_Libraries_and_Scripts/1_Imports_A02_t17: Fail, OK
 
-Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t04: Fail, OK # contains syntax error
+
+# co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/approxEquals_A04_t01: Fail
+LibTest/core/Expect/equals_A02_t01: Fail
+LibTest/core/Expect/identical_A02_t01: Fail
+LibTest/core/Expect/isFalse_A02_t01: Fail
+LibTest/core/Expect/isNotNull_A02_t01: Fail
+LibTest/core/Expect/isNull_A02_t01: Fail
+LibTest/core/Expect/isTrue_A02_t01: Fail
+LibTest/core/Expect/listEquals_A03_t01: Fail
+LibTest/core/Expect/notEquals_A02_t01: Fail
+LibTest/core/Expect/setEquals_A03_t01: Fail
+LibTest/core/Expect/stringEquals_A02_t01: Fail
+LibTest/core/Expect/throws_A01_t04: Fail
+LibTest/core/Future/chain_A02_t04: Fail
+LibTest/core/Future/chain_A02_t05: Fail
+LibTest/core/Future/transform_A02_t03: Fail
+LibTest/core/Future/transform_A02_t04: Fail
+LibTest/core/List/every_A04_t01: Fail
+LibTest/core/List/filter_A04_t01: Fail
+LibTest/core/List/forEach_A03_t01: Fail
+LibTest/core/List/List.from_A01_t01: Fail
+LibTest/core/List/operator_subscript_A01_t01: Fail
+LibTest/core/List/operator_subscript_A01_t02: Fail
+LibTest/core/List/operator_subscripted_assignment_A01_t02: Fail
+LibTest/core/List/operator_subscripted_assignment_A01_t01: Fail
+LibTest/core/List/setRange_A01_t01: Fail
+LibTest/core/Queue/addFirst_A01_t01: Fail
+LibTest/core/Set/intersection_A01_t03: Fail
+LibTest/core/String/toLowerCase_A01_t02: Fail
+LibTest/core/String/toUpperCase_A01_t02: Fail
+LibTest/core/String/trim_A01_t02: Fail
+LibTest/core/StringBuffer/add_A02_t01: Fail
+LibTest/core/StringBuffer/addAll_A02_t01: Fail
+LibTest/core/StringBuffer/clear_A02_t01: Fail
+
+
+# co19 issue 352 (use function expression with return type and name)
+LibTest/isolate/SendPort/send_A01_t01: Fail
+
+
+
 Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t02: Fail, OK # deprecated parameter syntax
 
 Language/03_Overview/1_Scoping_A02_t28: Fail # language change 1031
@@ -90,5 +131,7 @@
 Language/11_Expressions/22_Equality_A02_t03: Fail, OK # co19 issue 169
 
 
+
+
 [ $runtime == drt && ($compiler == none || $compiler == frog) ]
 *: Skip
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 0f9d5f3..c36a20f 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -21,6 +21,17 @@
 Language/15_Reference/1_Lexical_Rules_A01_t09: Fail # TODO(dart2dart-team): Please triage this failure.
 Language/15_Reference/1_Lexical_Rules_A01_t11: Fail # TODO(dart2dart-team): Please triage this failure.
 
+Language/03_Overview/1_Scoping_A01_t39: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t01: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t02: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t03: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t04: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t05: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t01: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t02: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: Fail # http://dartbug.com/7202
+
 
 # Calling unresolved class constructor:
 Language/03_Overview/2_Privacy_A01_t19: Fail
@@ -263,13 +274,11 @@
 Language/11_Expressions/11_Instance_Creation/2_Const_A06_t02: Fail # http://dartbug.com/5519
 Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: Fail # inherited from VM
 Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t01: Fail # inherited from VM
-Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t02: Fail # inherited from VM
 Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t02: Fail # inherited from VM
 Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail # inherited from VM
 Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t03: Fail # inherited from VM
 Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t04: Fail # http://dartbug.com/5519
 Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t06: Fail # inherited from VM
-Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t08: Fail # inherited from VM
 Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail # inherited from VM
 Language/11_Expressions/18_Assignment_A05_t02: Fail # inherited from VM
 Language/11_Expressions/18_Assignment_A05_t04: Fail, Pass, OK # Fails in minified, depends on method names.
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 9617c02..3ad85ec 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -68,7 +68,6 @@
 Language/11_Expressions/18_Assignment_A05_t02: Fail # TODO(ahe): Please triage this failure.
 Language/11_Expressions/18_Assignment_A05_t04: Fail # TODO(ahe): Please triage this failure.
 Language/11_Expressions/18_Assignment_A05_t05: Fail # TODO(ahe): Please triage this failure.
-Language/11_Expressions/18_Assignment_A08_t04: Fail # TODO(ahe): Please triage this failure.
 Language/11_Expressions/19_Conditional_A01_t14: Fail # TODO(ahe): Please triage this failure.
 Language/11_Expressions/19_Conditional_A01_t15: Fail # TODO(ahe): Please triage this failure.
 Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t14: Fail # TODO(ahe): Please triage this failure.
@@ -132,12 +131,8 @@
 Language/13_Libraries_and_Scripts/1_Imports_A02_t14: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/1_Imports_A02_t16: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/1_Imports_A02_t17: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/1_Imports_A02_t19: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/1_Imports_A02_t27: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/1_Imports_A02_t28: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/1_Imports_A03_t51: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/1_Imports_A05_t01: Fail # TODO(ahe): Please triage this failure.
-Language/13_Libraries_and_Scripts/2_Exports_A06_t02: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/3_Parts_A03_t02: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/4_Scripts_A01_t20: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/4_Scripts_A01_t21: Fail # TODO(ahe): Please triage this failure.
@@ -148,34 +143,19 @@
 Language/13_Libraries_and_Scripts/5_URIs_A01_t21: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/5_URIs_A01_t24: Fail # TODO(ahe): Please triage this failure.
 Language/13_Libraries_and_Scripts/5_URIs_A01_t25: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/3_Type_Declarations/1_Typedef_A07_t05: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/3_Type_Declarations/1_Typedef_A07_t06: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/3_Type_Declarations/1_Typedef_A07_t07: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A01_t04: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A01_t10: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A02_t02: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A02_t03: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A02_t04: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A02_t05: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A02_t06: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A02_t07: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A02_t08: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A02_t09: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A02_t10: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A03_t01: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A03_t02: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A03_t03: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A03_t04: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A03_t06: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A03_t07: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A03_t08: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A03_t09: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A03_t10: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A03_t11: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A03_t12: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A03_t13: Fail # TODO(ahe): Please triage this failure.
 Language/14_Types/5_Function_Types_A04_t01: Fail # TODO(ahe): Please triage this failure.
-Language/14_Types/5_Function_Types_A06_t01: Fail # TODO(ahe): Please triage this failure.
 Language/15_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: Fail # TODO(ahe): Please triage this failure.
 Language/15_Reference/1_Lexical_Rules_A01_t09: Fail # TODO(ahe): Please triage this failure.
 Language/15_Reference/1_Lexical_Rules_A01_t11: Fail # TODO(ahe): Please triage this failure.
@@ -201,8 +181,6 @@
 [ $compiler == dart2js && $unchecked ]
 LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A03_t01: Fail # TODO(ahe): Please triage this failure.
 
-Language/09_Generics/09_Generics_A05_t01: Fail # TODO(johnniwinther): Please triage this failure.
-
 [ $compiler == dart2js && $runtime == jsshell ]
 LibTest/core/double/round_A01_t01: Fail # TODO(ahe): Triage these tests.
 LibTest/core/double/toStringAsExponential_A01_t07: Fail # TODO(ahe): Triage these tests.
@@ -273,13 +251,6 @@
 LibTest/core/TypeError/srcType_A01_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/core/TypeError/url_A01_t01: Fail # TODO(ahe): Please triage this failure.
 
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t01: Fail # Checked mode failure for noSuchMethod type.
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t02: Fail # Checked mode failure for noSuchMethod type.
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t03: Fail # Checked mode failure for noSuchMethod type.
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t04: Fail # Checked mode failure for noSuchMethod type.
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A06_t01: Fail # Checked mode failure for noSuchMethod type.
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A06_t02: Fail # Checked mode failure for noSuchMethod type.
-
 Language/11_Expressions/11_Instance_Creation/1_New_A12_t02: Fail # http://dartbug.com/3970
 
 
@@ -586,9 +557,6 @@
 Language/14_Types/5_Function_Types_A01_t05: Fail # http://dartbug.com/5022
 Language/14_Types/5_Function_Types_A01_t06: Fail # http://dartbug.com/5022
 Language/14_Types/5_Function_Types_A01_t07: Fail # http://dartbug.com/5022
-Language/14_Types/5_Function_Types_A01_t08: Fail # http://dartbug.com/5022
-Language/14_Types/5_Function_Types_A01_t09: Fail # http://dartbug.com/5022
-Language/14_Types/5_Function_Types_A01_t11: Fail # http://dartbug.com/5022
 
 Language/13_Libraries_and_Scripts/4_Scripts_A03_t01: Fail # http://dartbug.com/5683
 Language/13_Libraries_and_Scripts/4_Scripts_A03_t03: Fail # http://dartbug.com/5683
@@ -614,3 +582,14 @@
 Language/14_Types/4_Interface_Types_A12_t10: Fail # http://dartbug.com/5020
 Language/14_Types/4_Interface_Types_A12_t14: Fail # http://dartbug.com/5020
 Language/14_Types/4_Interface_Types_A12_t16 :Fail # http://dartbug.com/5020
+
+Language/03_Overview/1_Scoping_A01_t39: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t01: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t02: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t03: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t04: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A06_t05: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t01: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t02: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: Fail # http://dartbug.com/7202
+Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: Fail # http://dartbug.com/7202
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 753a249..ae33a54 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -6,155 +6,154 @@
 Language/13_Libraries_and_Scripts/1_Imports_A02_t21: Crash # Dart issue 6060
 Language/13_Libraries_and_Scripts/1_Imports_A02_t22: Crash # Dart issue 6060
 
-Language/03_Overview/1_Scoping_A02_t32: Fail # TODO(vm-team): Please triage this failure.
-Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t10: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/3_Setters_A04_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/3_Setters_A04_t04: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/3_Setters_A04_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/4_Abstract_Instance_Members_A03_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/4_Abstract_Instance_Members_A03_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/4_Abstract_Instance_Members_A03_t04: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/4_Abstract_Instance_Members_A03_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/4_Abstract_Instance_Members_A04_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/4_Abstract_Instance_Members_A04_t06: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/08_Interfaces/5_Superinterfaces_A01_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/01_Constants_A03_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/01_Constants_A05_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/01_Constants_A06_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/01_Constants_A14_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/01_Constants_A20_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/01_Constants_A20_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t04: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t06: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/05_Strings_A02_t46: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/05_Strings_A02_t48: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/11_Instance_Creation/1_New_A02_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/11_Instance_Creation/1_New_A02_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/11_Instance_Creation/1_New_A09_t09: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t08: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/18_Assignment_A05_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/18_Assignment_A05_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/19_Conditional_A01_t10: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/19_Conditional_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/19_Conditional_A01_t12: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/19_Conditional_A01_t13: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/19_Conditional_A01_t14: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/19_Conditional_A01_t15: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t10: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t12: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t13: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t14: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t15: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/21_Bitwise_Expressions_A01_t12: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/21_Bitwise_Expressions_A01_t13: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/21_Bitwise_Expressions_A01_t14: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/21_Bitwise_Expressions_A01_t15: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/21_Bitwise_Expressions_A01_t16: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/21_Bitwise_Expressions_A01_t17: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/22_Equality_A01_t23: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/22_Equality_A01_t24: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/23_Relational_Expressions_A01_t18: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/23_Relational_Expressions_A01_t19: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/23_Relational_Expressions_A01_t20: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/23_Relational_Expressions_A01_t21: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/23_Relational_Expressions_A01_t22: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/23_Relational_Expressions_A01_t23: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/24_Shift_A01_t09: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/24_Shift_A01_t10: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/24_Shift_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/24_Shift_A01_t12: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/24_Shift_A01_t13: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/24_Shift_A01_t14: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/25_Additive_Expressions_A01_t07: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/25_Additive_Expressions_A01_t08: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/25_Additive_Expressions_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/25_Additive_Expressions_A01_t12: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/25_Additive_Expressions_A01_t13: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/25_Additive_Expressions_A01_t14: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t10: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t14: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t15: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t16: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t17: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t04: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t12: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t13: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t17: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t18: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t19: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t20: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t21: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/27_Unary_Expressions_A01_t22: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/28_Postfix_Expressions_A01_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/28_Postfix_Expressions_A01_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/28_Postfix_Expressions_A01_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/29_Assignable_Expressions_A01_t06: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/29_Assignable_Expressions_A01_t08: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/29_Assignable_Expressions_A01_t09: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/30_Identifier_Reference_A05_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/30_Identifier_Reference_A06_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/30_Identifier_Reference_A06_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/30_Identifier_Reference_A07_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/30_Identifier_Reference_A08_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/31_Type_Test_A01_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/11_Expressions/31_Type_Test_A01_t04: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/03_Variable_Declaration_A04_t07: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/04_Local_Function_Declaration_A02_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/06_For_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A01_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A02_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A02_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A02_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A03_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A03_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A04_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/09_Switch_A06_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/10_Try_A03_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/10_Try_A03_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/10_Try_A03_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/10_Try_A11_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/12_Statements/12_Labels_A01_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t04: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/1_Imports_A02_t29: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/1_Imports_A05_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/2_Exports_A04_t02: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/2_Exports_A04_t03: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/5_URIs_A01_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/5_URIs_A01_t04: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/5_URIs_A01_t05: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/5_URIs_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/5_URIs_A01_t14: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/5_URIs_A01_t15: Fail # TODO(vm-team): Please triage this failure.
-Language/13_Libraries_and_Scripts/5_URIs_A01_t21: Fail # TODO(vm-team): Please triage this failure.
-Language/14_Types/5_Function_Types_A04_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/14_Types/5_Function_Types_A06_t01: Fail # TODO(vm-team): Please triage this failure.
-Language/15_Reference/1_Lexical_Rules_A01_t09: Fail # TODO(vm-team): Please triage this failure.
-Language/15_Reference/1_Lexical_Rules_A01_t11: Fail # TODO(vm-team): Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A01_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A02_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A06_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/core/double/parse_A02_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/isolate/isolate_api/spawnUri_A01_t03: Fail # TODO(vm-team): Please triage this failure.
-LibTest/isolate/isolate_api/spawnUri_A01_t04: Fail # TODO(vm-team): Please triage this failure.
-LibTest/math/pow_A01_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/math/pow_A11_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/math/pow_A13_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/math/sin_A01_t01: Fail # TODO(vm-team): Please triage this failure.
+Language/03_Overview/1_Scoping_A02_t32: Fail # Dart issue 6556
+Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t10: Fail # co19 issue 348
+Language/07_Classes/3_Setters_A04_t01: Fail # Dart issue 5840
+Language/07_Classes/3_Setters_A04_t04: Fail # Dart issue 5840
+Language/07_Classes/3_Setters_A04_t05: Fail # Dart issue 5840
+Language/07_Classes/4_Abstract_Instance_Members_A03_t02: Fail # Dart issue 978
+Language/07_Classes/4_Abstract_Instance_Members_A03_t03: Fail # Dart issue 978
+Language/07_Classes/4_Abstract_Instance_Members_A03_t04: Fail # Dart issue 978
+Language/07_Classes/4_Abstract_Instance_Members_A03_t05: Fail # Dart issue 978
+Language/07_Classes/4_Abstract_Instance_Members_A04_t05: Fail # Dart issue 978
+Language/07_Classes/4_Abstract_Instance_Members_A04_t06: Fail # Dart issue 978
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail # Dart issue 6954
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: Fail # Dart issue 811
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: Fail # Dart issue 811
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: Fail # Dart issue 811
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: Fail # Dart issue 811
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: Fail # Dart issue 811
+Language/08_Interfaces/5_Superinterfaces_A01_t02: Fail # Dart issue 7245
+Language/11_Expressions/01_Constants_A03_t01: Fail # Dart issue 5214
+Language/11_Expressions/01_Constants_A05_t01: Fail # Dart issue 5832
+Language/11_Expressions/01_Constants_A06_t01: Fail # Dart issue 5214
+Language/11_Expressions/01_Constants_A14_t01: Fail # Dart issue 5214
+Language/11_Expressions/01_Constants_A20_t02: Fail # Dart issue 6556
+Language/11_Expressions/01_Constants_A20_t03: Fail # Dart issue 6556
+Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t04: Fail # Dart issue 7246
+Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t05: Fail # Dart issue 7246
+Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t06: Fail # Dart issue 7246
+Language/11_Expressions/05_Strings_A02_t46: Fail # Dart issue 4009
+Language/11_Expressions/05_Strings_A02_t48: Fail # Dart issue 4009
+Language/11_Expressions/11_Instance_Creation/1_New_A02_t03: Fail # Dart issue 3309
+Language/11_Expressions/11_Instance_Creation/1_New_A02_t05: Fail # Dart issue 7247
+Language/11_Expressions/11_Instance_Creation/1_New_A09_t09: Fail # Dart issue 1372
+Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: Fail # Dart issue 5775
+Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail # Dart issue 6449
+Language/11_Expressions/18_Assignment_A05_t02: Fail # Dart issue 6449
+Language/11_Expressions/18_Assignment_A05_t04: Fail, OK # co19 issue 350.
+Language/11_Expressions/18_Assignment_A05_t05: Fail # Dart issue 6449
+Language/11_Expressions/19_Conditional_A01_t10: Fail # Dart issue 7251
+Language/11_Expressions/19_Conditional_A01_t11: Fail # Dart issue 7252
+Language/11_Expressions/19_Conditional_A01_t12: Fail # Dart issue 7251
+Language/11_Expressions/19_Conditional_A01_t13: Fail # Dart issue 7252
+Language/11_Expressions/19_Conditional_A01_t14: Fail # Dart issue 7251
+Language/11_Expressions/19_Conditional_A01_t15: Fail # Dart issue 7252
+Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t10: Fail # Dart issue 7251
+Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t11: Fail # Dart issue 7251
+Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t12: Fail # Dart issue 7251
+Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t13: Fail # Dart issue 7251
+Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t14: Fail # Dart issue 7251
+Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t15: Fail # Dart issue 7251
+Language/11_Expressions/21_Bitwise_Expressions_A01_t12: Fail # Dart issue 7251
+Language/11_Expressions/21_Bitwise_Expressions_A01_t13: Fail # Dart issue 7251
+Language/11_Expressions/21_Bitwise_Expressions_A01_t14: Fail # Dart issue 7251
+Language/11_Expressions/21_Bitwise_Expressions_A01_t15: Fail # Dart issue 7251
+Language/11_Expressions/21_Bitwise_Expressions_A01_t16: Fail # Dart issue 7251
+Language/11_Expressions/21_Bitwise_Expressions_A01_t17: Fail # Dart issue 7251
+Language/11_Expressions/22_Equality_A01_t23: Fail # Dart issue 7254
+Language/11_Expressions/22_Equality_A01_t24: Fail # Dart issue 7254
+Language/11_Expressions/23_Relational_Expressions_A01_t18: Fail # Dart issue 7256
+Language/11_Expressions/23_Relational_Expressions_A01_t19: Fail # Dart issue 7256
+Language/11_Expressions/23_Relational_Expressions_A01_t20: Fail # Dart issue 7256
+Language/11_Expressions/23_Relational_Expressions_A01_t21: Fail # Dart issue 7256
+Language/11_Expressions/23_Relational_Expressions_A01_t22: Fail # Dart issue 7256
+Language/11_Expressions/23_Relational_Expressions_A01_t23: Fail # Dart issue 7256
+Language/11_Expressions/24_Shift_A01_t09: Fail # Dart issue 7256
+Language/11_Expressions/24_Shift_A01_t10: Fail # Dart issue 7256
+Language/11_Expressions/24_Shift_A01_t11: Fail # Dart issue 7256
+Language/11_Expressions/24_Shift_A01_t12: Fail # Dart issue 7256
+Language/11_Expressions/24_Shift_A01_t13: Fail # Dart issue 7256
+Language/11_Expressions/24_Shift_A01_t14: Fail # Dart issue 7256
+Language/11_Expressions/25_Additive_Expressions_A01_t07: Fail # Dart issue 7256
+Language/11_Expressions/25_Additive_Expressions_A01_t08: Fail # Dart issue 7256
+Language/11_Expressions/25_Additive_Expressions_A01_t11: Fail # Dart issue 7256
+Language/11_Expressions/25_Additive_Expressions_A01_t12: Fail # Dart issue 7256
+Language/11_Expressions/25_Additive_Expressions_A01_t13: Fail # Dart issue 7256
+Language/11_Expressions/25_Additive_Expressions_A01_t14: Fail # Dart issue 7256
+Language/11_Expressions/26_Multiplicative_Expressions_A01_t10: Fail # Dart issue 7256
+Language/11_Expressions/26_Multiplicative_Expressions_A01_t11: Fail # Dart issue 7256
+Language/11_Expressions/26_Multiplicative_Expressions_A01_t14: Fail # Dart issue 7256
+Language/11_Expressions/26_Multiplicative_Expressions_A01_t15: Fail # Dart issue 7256
+Language/11_Expressions/26_Multiplicative_Expressions_A01_t16: Fail # Dart issue 7256
+Language/11_Expressions/26_Multiplicative_Expressions_A01_t17: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t02: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t04: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t05: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t11: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t12: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t13: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t17: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t18: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t19: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t20: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t21: Fail # Dart issue 7256
+Language/11_Expressions/27_Unary_Expressions_A01_t22: Fail # Dart issue 7256
+Language/11_Expressions/28_Postfix_Expressions_A01_t02: Fail # Dart issue 7256
+Language/11_Expressions/28_Postfix_Expressions_A01_t03: Fail # Dart issue 7256
+Language/11_Expressions/28_Postfix_Expressions_A01_t05: Fail # Dart issue 7256
+Language/11_Expressions/29_Assignable_Expressions_A01_t06: Fail # Dart issue 7256
+Language/11_Expressions/29_Assignable_Expressions_A01_t08: Fail # Dart issue 7256
+Language/11_Expressions/29_Assignable_Expressions_A01_t09: Fail # Dart issue 7256
+Language/11_Expressions/30_Identifier_Reference_A05_t02: Fail # Dart issue 2492
+Language/11_Expressions/30_Identifier_Reference_A06_t01: Fail # Dart issue 7257
+Language/11_Expressions/30_Identifier_Reference_A06_t02: Fail # Dart issue 7257
+Language/11_Expressions/30_Identifier_Reference_A07_t01: Fail # Dart issue 7257
+Language/11_Expressions/30_Identifier_Reference_A08_t02: Fail # Dart issue 5802
+Language/11_Expressions/31_Type_Test_A01_t02: Fail # Dart issue 7258
+Language/11_Expressions/31_Type_Test_A01_t04: Fail # Dart issue 7258
+Language/12_Statements/03_Variable_Declaration_A04_t07: Fail # Dart issue 7305
+Language/12_Statements/04_Local_Function_Declaration_A02_t02: Fail # Dart issue 5773
+Language/12_Statements/06_For_A01_t11: Fail # Dart issue 5675
+Language/12_Statements/09_Switch_A01_t02: Fail # Dart issue 2238
+Language/12_Statements/09_Switch_A02_t01: Fail # Dart issue 7306
+Language/12_Statements/09_Switch_A02_t02: Fail # Dart issue 7307
+Language/12_Statements/09_Switch_A02_t03: Fail # Dart issue 7308
+Language/12_Statements/09_Switch_A03_t01: Fail # Dart issue 7307
+Language/12_Statements/09_Switch_A03_t02: Fail # Dart issue 7307
+Language/12_Statements/09_Switch_A04_t01: Fail # Dart issue 6897
+Language/12_Statements/09_Switch_A06_t02: Fail # Dart issue 5837
+Language/12_Statements/10_Try_A03_t01: Fail # Dart issue 7311
+Language/12_Statements/10_Try_A03_t02: Fail # Dart issue 7311
+Language/12_Statements/10_Try_A03_t03: Fail # Dart issue 7311
+Language/12_Statements/10_Try_A11_t01: Fail # Dart issue 430
+Language/12_Statements/12_Labels_A01_t03: Fail # Dart issue 2238
+Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t04: Fail # Dart issue 5839
+Language/13_Libraries_and_Scripts/1_Imports_A02_t29: Fail # Dart issue 6783
+Language/13_Libraries_and_Scripts/1_Imports_A05_t01: Fail # Dart issue 3206
+Language/13_Libraries_and_Scripts/2_Exports_A04_t02: Fail # Dart issue 6134
+Language/13_Libraries_and_Scripts/2_Exports_A04_t03: Fail # Dart issue 6134
+Language/13_Libraries_and_Scripts/5_URIs_A01_t01: Fail # Dart issue 6352
+Language/13_Libraries_and_Scripts/5_URIs_A01_t04: Fail # Dart issue 7317
+Language/13_Libraries_and_Scripts/5_URIs_A01_t05: Fail # Dart issue 7317
+Language/13_Libraries_and_Scripts/5_URIs_A01_t11: Fail # Dart issue 6352
+Language/13_Libraries_and_Scripts/5_URIs_A01_t14: Fail # Dart issue 7317
+Language/13_Libraries_and_Scripts/5_URIs_A01_t15: Fail # Dart issue 7317
+Language/13_Libraries_and_Scripts/5_URIs_A01_t21: Fail # Dart issue 6352
+Language/14_Types/5_Function_Types_A04_t01: Fail # Dart issue 6921
+Language/14_Types/5_Function_Types_A06_t01: Fail # Dart issue 1604
+Language/15_Reference/1_Lexical_Rules_A01_t09: Fail # Dart issue 2687
+Language/15_Reference/1_Lexical_Rules_A01_t11: Fail # Dart issue 2687
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A01_t01: Fail # co19 issue 353
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A02_t01: Fail # co19 issue 353
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A06_t01: Fail # co19 issue 353
+LibTest/core/double/parse_A02_t01: Fail # Dart issue 1929
+LibTest/isolate/isolate_api/spawnUri_A01_t03: Fail # Dart issue 5222
+LibTest/isolate/isolate_api/spawnUri_A01_t04: Fail # Dart issue 5222
+LibTest/math/pow_A01_t01: Fail # Dart issue 7318
+LibTest/math/pow_A11_t01: Fail # Dart issue 449
+LibTest/math/pow_A13_t01: Fail # Dart issue 449
+LibTest/math/sin_A01_t01: Fail # Dart issue 7318
 
 Language/05_Variables/05_Variables_A05_t04: Fail # Dart issue 5881
 Language/05_Variables/05_Variables_A05_t11: Fail # Dart issue 5885
diff --git a/tests/compiler/dart2js/deprecated_features_test.dart b/tests/compiler/dart2js/deprecated_features_test.dart
new file mode 100644
index 0000000..8cd931f
--- /dev/null
+++ b/tests/compiler/dart2js/deprecated_features_test.dart
@@ -0,0 +1,108 @@
+// 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.
+
+// Test that deprecated language features are diagnosed correctly.
+
+import '../../../sdk/lib/_internal/compiler/compiler.dart';
+import 'dart:uri';
+import '../../utils/dummy_compiler_test.dart' as dummy;
+
+main() {
+  StringBuffer messages = new StringBuffer();
+  void handler(Uri uri, int begin, int end, String message, Diagnostic kind) {
+    if (kind == Diagnostic.VERBOSE_INFO) return;
+    if (identical(kind.name, 'source map')) return;
+    if (uri == null) {
+      messages.add('$kind: $message\n');
+    } else {
+      Expect.equals('main:${uri.path}', '$uri');
+      String source = TEST_SOURCE[uri.path];
+      Expect.isNotNull(source);
+      messages.add('$begin<${source.substring(begin, end)}>:${uri.path}:'
+                   '$kind: $message\n');
+    }
+  }
+
+  Future<String> provider(Uri uri) {
+    if (uri.scheme != "main") return dummy.provider(uri);
+    String source = TEST_SOURCE[uri.path];
+    Expect.isNotNull(source);
+    return (new Completer<String>()..complete(source)).future;
+  }
+
+  String code = compile(new Uri.fromComponents(scheme: 'main'),
+                        new Uri.fromComponents(scheme: 'lib', path: '/'),
+                        new Uri.fromComponents(scheme: 'package', path: '/'),
+                        provider, handler).value;
+  if (code == null) {
+    throw 'Compilation failed: ${messages}';
+  }
+  Expect.stringEquals(
+      // This string is comprised of lines of the following format:
+      //
+      // offset<source>:path:kind: message
+      //
+      // "offset" is the character offset from the beginning of TEST_SOURCE.
+      // "source" is the substring of TEST_SOURCE that the compiler is
+      // indicating as erroneous.
+      // "path" is the URI path.
+      // "kind" is the result of calling toString on a [Diagnostic] object.
+      // "message" is the expected message as a [String].  This is a
+      // short-term solution and should eventually changed to include
+      // a symbolic reference to a MessageKind.
+      "0<#library('test');>::${deprecatedMessage('# tags')}\n"
+      "38<interface>::${deprecatedMessage('interface declarations')}\n"
+      "19<part 'part.dart';>::${deprecatedMessage('missing part-of tag')}\n"
+      "0<>:/part.dart:info: Note: This file has no part-of tag, but it is being"
+      " used as a part.\n"
+      "163<Fisk>::${deprecatedMessage('interface factories')}\n"
+
+      // TODO(ahe): Should be <Fisk.hest>.
+      "183<Fisk>::${deprecatedMessage('interface factories')}\n"
+
+      // TODO(ahe): Should be <bar>.
+      "109<Foo>::${deprecatedMessage('conflicting constructor')}\n"
+
+      "129<bar>::info: This member conflicts with a constructor.\n"
+      "200<Dynamic>::${deprecatedMessage('Dynamic')}\n"
+      "221<()>::${deprecatedMessage('getter parameters')}\n",
+      messages.toString());
+}
+
+deprecatedMessage(feature) {
+  return
+    "warning: Warning: deprecated language feature, $feature"
+    ", will be removed in a future Dart milestone.";
+}
+
+const Map<String, String> TEST_SOURCE =
+  const <String, String>{ '': """
+#library('test');
+
+part 'part.dart';
+
+interface Fisk default Foo {
+  Fisk();
+  Fisk.hest();
+}
+
+class Foo {
+  Foo.bar();
+  static bar() => new Foo.bar();
+  factory Fisk() {}
+  factory Fisk.hest() {}
+  Dynamic fisk;
+  get x() => null;
+}
+
+main() {
+  var a = Foo.bar();
+  var b = new Foo.bar();
+  new Fisk();
+  new Fisk.hest();
+}
+""",
+    // TODO(ahe): Why isn't this 'part.dart'? Why the leading slash?
+    '/part.dart': '',
+  };
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 140cec2..883f02b 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -81,7 +81,7 @@
   class Object {}
   class Type {}
   class Function {}
-  class List<T> {}
+  class List<E> {}
   abstract class Map<K,V> {}
   class Closure {}
   class Null {}
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index 2b1fac6..f6f87c5 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -628,6 +628,37 @@
   Link<DartType> supertypes = aElement.allSupertypes;
   Expect.equals(<String>['B', 'C', 'Object'].toString(),
                 asSortedStrings(supertypes).toString());
+
+  compiler = new MockCompiler();
+  compiler.parseScript("""class A<T> {}
+                          class B<Z,W> extends A<int> implements I<Z,List<W>> {}
+                          class I<X,Y> {}
+                          class C extends B<bool,String> {}
+                          main() { return new C(); }""");
+  mainElement = compiler.mainApp.find(MAIN);
+  compiler.resolver.resolve(mainElement);
+  Expect.equals(0, compiler.warnings.length);
+  Expect.equals(0, compiler.errors.length);
+  aElement = compiler.mainApp.find(buildSourceString("C"));
+  supertypes = aElement.allSupertypes;
+  // Object is once per inheritance path, that is from both A and I.
+  Expect.equals(<String>['A<int>', 'B<bool, String>', 'I<bool, List<String>>',
+                         'Object', 'Object'].toString(),
+                asSortedStrings(supertypes).toString());
+
+  compiler = new MockCompiler();
+  compiler.parseScript("""class A<T> {}
+                          class D extends A<E> {}
+                          class E extends D {}
+                          main() { return new E(); }""");
+  mainElement = compiler.mainApp.find(MAIN);
+  compiler.resolver.resolve(mainElement);
+  Expect.equals(0, compiler.warnings.length);
+  Expect.equals(0, compiler.errors.length);
+  aElement = compiler.mainApp.find(buildSourceString("E"));
+  supertypes = aElement.allSupertypes;
+  Expect.equals(<String>['A<E>', 'D', 'Object'].toString(),
+                asSortedStrings(supertypes).toString());
 }
 
 testInitializers() {
diff --git a/tests/compiler/dart2js_extra/closure_capture2_test.dart b/tests/compiler/dart2js_extra/closure_capture2_test.dart
index b24fda9..21f91e4 100644
--- a/tests/compiler/dart2js_extra/closure_capture2_test.dart
+++ b/tests/compiler/dart2js_extra/closure_capture2_test.dart
@@ -24,8 +24,8 @@
 }
 
 closure1() {
-  // f captures variable $0 which could yield to troubles with HForeign if we
-  // don't mangle correctly.
+  // f captures variable $0 which once could yield to troubles with HForeign if
+  // we did not mangle correctly.
   var $1 = 499;
   // TODO(floitsch): remove name from functions.
   var f = fun() { return $1; };
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 9e569d2..e385dd9 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -23,6 +23,9 @@
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
+[ $compiler == dart2js && $minified ]
+to_string_test: Fail # Issue 7179.
+
 [ $jscl ]
 timer_test: Fail, OK # Timer is only supported in browsers.
 mirror_test: Fail, OK # Timer is only supported in browsers.
diff --git a/tests/compiler/dart2js_native/native_class_fields_test.dart b/tests/compiler/dart2js_native/native_class_fields_test.dart
new file mode 100644
index 0000000..8221eec
--- /dev/null
+++ b/tests/compiler/dart2js_native/native_class_fields_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify that native fields on classes are not renamed by the minifier.
+class A native "*A" {
+  int myLongPropertyName;
+  int getValue;
+
+  int method(int z) => myLongPropertyName;
+}
+
+
+void setup() native r"""
+function getter() {
+  return ++this.getValue;
+}
+
+function setter(x) {
+  this.getValue += 10;
+}
+  
+function A(){
+  var a = Object.create(
+      { constructor: { name: 'A'}},
+      { myLongPropertyName: { get: getter,
+                              set: setter,
+                              configurable: false,
+                              writeable: false
+                            }
+      });
+  a.getValue = 0;
+  return a;
+}
+
+makeA = function(){return new A;};
+""";
+
+A makeA() native { return new A(); }
+
+main() {
+  setup();
+  var a = makeA();
+  a.myLongPropertyName = 21;
+  int gotten = a.myLongPropertyName;
+  Expect.equals(11, gotten);
+
+  var a2 = makeA();
+  if (a2 is A) {
+    // Inside this 'if' the compiler knows that a2 is an A, so it is tempted
+    // to access myLongPropertyName directly, using its minified name.  But
+    // renaming of native properties can only work using getters and setters
+    // that access the original name.
+    a2.myLongPropertyName = 21;
+    int gotten = a2.myLongPropertyName;
+    Expect.equals(11, gotten);
+  }
+}
+
diff --git a/tests/compiler/dart2js_native/native_field_name_test.dart b/tests/compiler/dart2js_native/native_field_name_test.dart
index d479d82..c1bb426 100644
--- a/tests/compiler/dart2js_native/native_field_name_test.dart
+++ b/tests/compiler/dart2js_native/native_field_name_test.dart
@@ -12,7 +12,7 @@
 }
 
 
-// This code is inside the setup function, so the function names are not 
+// This code is inside the setup function, so the function names are not
 // accessible, but the makeA variable is global through the magic of JS scoping.
 // The contents of this are of course not analyzable by the compiler.
 void setup() native r"""
diff --git a/tests/compiler/dart2js_native/native_novel_html_test.dart b/tests/compiler/dart2js_native/native_novel_html_test.dart
new file mode 100644
index 0000000..485d2f6
--- /dev/null
+++ b/tests/compiler/dart2js_native/native_novel_html_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test to see if novel HTML tags are interpreted as HTMLElement.
+
+class Element native "*HTMLElement" {
+  String dartMethod(int x) => 'dartMethod(${nativeMethod(x+1)})';
+  String nativeMethod(int x) native;
+}
+
+makeE() native;
+makeF() native;
+
+void setup() native """
+// A novel HTML element.
+function HTMLGoofyElement(){}
+HTMLGoofyElement.prototype.nativeMethod = function(a) {
+  return 'Goofy.nativeMethod(' + a  + ')';
+};
+makeE = function(){return new HTMLGoofyElement};
+
+// A non-HTML element with a misleading name.
+function HTMLFakeyElement(){}
+HTMLFakeyElement.prototype.nativeMethod = function(a) {
+  return 'Fakey.nativeMethod(' + a  + ')';
+};
+makeF = function(){return new HTMLFakeyElement};
+
+// Make the HTMLGoofyElement look like a real host object.
+var theRealObjectToString = Object.prototype.toString;
+Object.prototype.toString = function() {
+  if (this instanceof HTMLGoofyElement) return '[object HTMLGoofyElement]';
+  return theRealObjectToString.call(this);
+}
+""";
+
+
+main() {
+  setup();
+
+  var e = makeE();
+  Expect.equals('Goofy.nativeMethod(10)', e.nativeMethod(10));
+  Expect.equals('dartMethod(Goofy.nativeMethod(11))', e.dartMethod(10));
+
+  var f = makeF();
+  Expect.throws(() => f.nativeMethod(20), (e) => e is NoSuchMethodError,
+      'fake HTML Element must not run Dart method on native class');
+  Expect.throws(() => f.dartMethod(20), (e) => e is NoSuchMethodError,
+      'fake HTML Element must not run native method on native class');
+}
diff --git a/tests/corelib/bool_hashcode_test.dart b/tests/corelib/bool_hashcode_test.dart
new file mode 100644
index 0000000..63dbcb5
--- /dev/null
+++ b/tests/corelib/bool_hashcode_test.dart
@@ -0,0 +1,13 @@
+// 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.
+
+class BoolHashCodeTest {
+  static testMain() {
+    Expect.notEquals(true.hashCode, false.hashCode);
+  }
+}
+
+main() {
+  BoolHashCodeTest.testMain();
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index f48942d..2843f20 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -56,6 +56,7 @@
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
 [ $compiler == dart2js && $runtime == safari ]
+null_nosuchmethod_test: Fail # TODO(ahe): Please triage this failure.
 core_runtime_types_test: Fail
 
 [ $compiler == dart2js && $runtime == ie9 ]
diff --git a/tests/html/form_data_test.dart b/tests/html/form_data_test.dart
index 61f0147..6ea5381 100644
--- a/tests/html/form_data_test.dart
+++ b/tests/html/form_data_test.dart
@@ -29,10 +29,18 @@
 
   test('appendTest', () {
     var form = new FormData();
-    form.append('test', '1', 'foo');
-    form.append('username', 'Elmo', 'foo');
-    form.append('address', '1 Sesame Street', 'foo');
+    form.append('test', '1');
+    form.append('username', 'Elmo');
+    form.append('address', '1 Sesame Street');
     form.append('password', '123456', 'foo');
     expect(form, isNotNull);
   });
+
+  test('appendBlob', () {
+    var form = new FormData();
+    var blob = new Blob(
+        ['Indescribable... Indestructible! Nothing can stop it!'],
+        'text/plain');
+    form.append('theBlob', blob, 'theBlob.txt');
+  });
 }
diff --git a/tests/html/html.status b/tests/html/html.status
index 0326285..8825886 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -11,6 +11,11 @@
 
 [ $runtime == chrome ]
 contentelement_test: Fail   # Issue 5445: not currently supported on chrome stable.
+input_element_test/date: Pass, Fail      # Chrome stable does not support this input type.
+input_element_test/datetime: Fail        # Chrome stable does not support this input type.
+input_element_test/datetime-local: Fail  # Chrome stable does not support this input type.
+input_element_test/month: Fail           # Chrome stable does not support this input type.
+input_element_test/week: Fail            # Chrome stable does not support this input type.
 
 [ $runtime == chrome || $runtime == drt]
 audiobuffersourcenode_test: Pass, Fail  # AudiobufferSourceNode is flaky on Chrome and Dartium.
@@ -75,6 +80,12 @@
 indexeddb_3_test: Fail
 indexeddb_4_test: Fail
 inner_frame_test: Skip
+input_element_test/date: Fail            # IE10 does not support this input type.
+input_element_test/datetime: Fail        # IE10 does not support this input type.
+input_element_test/datetime-local: Fail  # IE10 does not support this input type.
+input_element_test/month: Fail           # IE10 does not support this input type.
+input_element_test/time: Fail            # IE10 does not support this input type.
+input_element_test/week: Fail            # IE10 does not support this input type.
 isolates_test: Skip
 localstorage_test: Fail
 measurement_test: Fail, Pass
@@ -134,6 +145,14 @@
 indexeddb_2_test: Fail
 indexeddb_3_test: Fail
 indexeddb_4_test: Fail
+input_element_test/date: Fail            # IE9 does not support this input type.
+input_element_test/datetime: Fail        # IE9 does not support this input type.
+input_element_test/datetime-local: Fail  # IE9 does not support this input type.
+input_element_test/month: Fail           # IE9 does not support this input type.
+input_element_test/range: Fail           # IE9 does not support this input type.
+input_element_test/time: Fail            # IE9 does not support this input type.
+input_element_test/week: Fail            # IE9 does not support this input type.
+
 messageevent_test: Fail
 mutationobserver_test: Fail
 postmessage_structured_test: Skip   # BUG(5685): times out.
@@ -157,53 +176,39 @@
 xhr_cross_origin_test: Fail # Issue 6016.
 
 [ $runtime == safari ]
+# TODO(ahe, efortuna): These tests need to be retriaged now that we're testing
+# with Safari 6.
+audiocontext_test: Crash, Fail # TODO(ahe): Please triage this failure.
+svgelement_test/innerHtml: Crash, Fail, Pass # TODO(ahe): Please triage this failure.
+svgelement_test/outerHtml: Crash, Fail, Pass # TODO(ahe): Please triage this failure.
+element_test/elements: Crash, Fail # TODO(ahe): Please triage this failure.
+element_test/children: Crash, Fail, Pass # TODO(ahe): Please triage this failure.
+element_test/attributes: Pass, Crash, Fail # TODO(ahe): Please triage this failure.
 performance_api_test: Fail # window.performance.timing not in Safari 6.
 indexeddb_1_test: Fail # indexedDB not in Safari 6.
 indexeddb_2_test: Fail # indexedDB not in Safari 6.
 indexeddb_3_test: Fail # indexedDB not in Safari 6.
 indexeddb_4_test: Fail # indexedDB not in Safari 6.
+input_element_test/date: Fail            # Safari does not support this input type.
+input_element_test/datetime: Fail        # Safari does not support this input type.
+input_element_test/datetime-local: Fail  # Safari does not support this input type.
+input_element_test/month: Fail, Crash    # Safari does not support this input type.
+input_element_test/range: Fail, Crash    # TODO(efortuna): Please triage this failure.
+input_element_test/time: Fail, Crash     # Safari does not support this input type.
+input_element_test/week: Fail, Crash     # Safari does not support this input type.
 fileapi_test: Fail # requestFileSystem not supported in Safari 6.
 datalistelement_test: Fail # HTMLDataListElement not yet supported in Safari.
 contentelement_test: Fail # Safari 6 does not support content element.
-# The following tests all fail in Safari 5.1. (NOT Mountain Lion). These will go
-# away after we upgrade the buildbots to Mountain Lion after M1.
+# TODO: The following tests need to be triaged to understand why they are
+# failing (They are expected to pass in Safari 6).
 # TODO(efortuna): Make our test framework able to separate tests out by browser
 # version.
-audiobuffersourcenode_test: Fail
-audiocontext_test: Fail
-blob_constructor_test: Fail
-canvas_pixel_array_type_alias_test: Fail
-canvas_test: Fail # createImageData not in Safari 5.
-canvasrenderingcontext2d_test: Fail
 datalistelement_test: Pass,Fail
-document_test: Fail
-dom_constructors_test: Fail
-element_test/additionalConstructors: Fail
-element_test/attributes: Fail, Crash
-element_test/constructors: Fail
-element_test/elements: Crash
-element_test/eventListening: Fail
-element_test/_ElementList: Fail, Crash
-element_test/queryAll: Fail, Crash
-element_add_test: Fail
-element_constructor_1_test: Fail
-element_webkit_test: Fail
-exceptions_test: Fail
-instance_of_test: Fail
-mutationobserver_test: Fail
-native_gc_test: Fail
 node_test: Skip # Issue 6457
-serialized_script_value_test: Fail
-svgelement2_test: Fail
-svgelement_test/constructors: Crash
-svgelement_test/css: Crash
-svgelement_test/additionalConstructors: Fail
-svgelement_test/elementget: Fail
-svgelement_test/elementset: Fail
-svgelement_test/innerHtml: Crash, Fail
-svgelement_test/outerHtml: Fail
-svgelement_test/svg: Fail
-url_test: Fail
+svgelement_test/elementset: Crash, Pass
+svgelement_test/elementget: Crash, Pass
+svgelement_test/css: Crash, Pass
+element_test/eventListening: Crash, Pass
 
 [ $runtime == opera && $system == windows ]
 htmlelement_test: Fail, Pass
@@ -269,6 +274,13 @@
 indexeddb_4_test: Fail     # FF disables indexedDB from file URLs.
 # setup code fails. prepare. (DOM callback has errors) Caught [object Event]
 inner_frame_test: Skip
+input_element_test/date: Fail            # FF does not support this input type.
+input_element_test/datetime: Fail        # FF does not support this input type.
+input_element_test/datetime-local: Fail  # FF does not support this input type.
+input_element_test/month: Fail           # FF does not support this input type.
+input_element_test/time: Fail            # FF does not support this input type.
+input_element_test/week: Fail            # FF does not support this input type.
+input_element_test/range: Fail           # FF does not support this input type.
 # Interfaces not implemented: SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGStylable
 svg_3_test: Fail
 svgelement_test/additionalConstructors: Fail
diff --git a/tests/html/input_element_test.dart b/tests/html/input_element_test.dart
new file mode 100644
index 0000000..d8c80ce
--- /dev/null
+++ b/tests/html/input_element_test.dart
@@ -0,0 +1,154 @@
+library input_element_test;
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
+import 'dart:html';
+
+main() {
+  useHtmlIndividualConfiguration();
+
+  test('hidden', () {
+    var e = new HiddenInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'hidden');
+  });
+
+  test('search', () {
+    var e = new SearchInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'search');
+  });
+
+  test('text', () {
+    var e = new TextInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'text');
+  });
+
+  test('url', () {
+    var e = new UrlInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'url');
+  });
+
+  test('telephone', () {
+    var e = new TelephoneInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'tel');
+  });
+
+  test('email', () {
+    var e = new EmailInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'email');
+  });
+
+  test('password', () {
+    var e = new PasswordInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'password');
+  });
+
+  group('datetime', () {
+    test('constructor', () {
+      var e = new DateTimeInputElement();
+      expect(e is InputElement, true);
+      expect(e.type, 'datetime');
+    });
+  });
+
+  group('date', () {
+    test('constructor', () {
+      var e = new DateInputElement();
+      expect(e is InputElement, true);
+      expect(e.type, 'date');
+    });
+  });
+
+  group('month', () {
+    test('constructor', () {
+      var e = new MonthInputElement();
+      expect(e is InputElement, true);
+      expect(e.type, 'month');
+    });
+  });
+
+  group('week', () {
+    test('constructor', () {
+      var e = new WeekInputElement();
+      expect(e is InputElement, true);
+      expect(e.type, 'week');
+    });
+  });
+
+  group('time', () {
+    test('constructor', () {
+      var e = new TimeInputElement();
+      expect(e is InputElement, true);
+      expect(e.type, 'time');
+    });
+  });
+
+  group('datetime-local', () {
+    test('constructor', () {
+      var e = new LocalDateTimeInputElement();
+      expect(e is InputElement, true);
+      expect(e.type, 'datetime-local');
+    });
+  });
+
+  test('number', () {
+    var e = new NumberInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'number');
+  });
+
+  group('range', () {
+    test('constructor', () {
+      var e = new RangeInputElement();
+      expect(e is InputElement, true);
+      expect(e.type, 'range');
+    });
+  });
+
+  test('checkbox', () {
+    var e = new CheckboxInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'checkbox');
+  });
+
+  test('radio', () {
+    var e = new RadioButtonInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'radio');
+  });
+
+  test('file', () {
+    var e = new FileUploadInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'file');
+  });
+
+  test('submit', () {
+    var e = new SubmitButtonInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'submit');
+  });
+
+  test('image', () {
+    var e = new ImageButtonInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'image');
+  });
+
+  test('reset', () {
+    var e = new ResetButtonInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'reset');
+  });
+
+  test('button', () {
+    var e = new ButtonInputElement();
+    expect(e is InputElement, true);
+    expect(e.type, 'button');
+  });
+}
diff --git a/tests/html/unknownelement_test.dart b/tests/html/unknownelement_test.dart
index fda531e..5b1a8d2 100644
--- a/tests/html/unknownelement_test.dart
+++ b/tests/html/unknownelement_test.dart
@@ -54,7 +54,7 @@
             switch (name) {
               case 'get:y':
                 return map['y'];
-              case 'set:y':
+              case 'set:y=':
                 map['y'] = args[0];
                 return;
             }
diff --git a/tests/language/arithmetic_test.dart b/tests/language/arithmetic_test.dart
index 9c06276..5c36ddf 100644
--- a/tests/language/arithmetic_test.dart
+++ b/tests/language/arithmetic_test.dart
@@ -55,11 +55,6 @@
       b = -1;
       Expect.equals(1 << i, a ~/ b);
     }
-    for (int i = 0; i < 80; i++) {
-      a = -1 << i;
-      b = -1;
-      Expect.equals(1 << i, a ~/ b);
-    }
     a = 22;
     b = 4.0;
     // Smi & double.
diff --git a/tests/language/invocation_mirror2_test.dart b/tests/language/invocation_mirror2_test.dart
new file mode 100644
index 0000000..de6fcc2
--- /dev/null
+++ b/tests/language/invocation_mirror2_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+class C {
+  var im;
+  noSuchMethod(im) => this.im = im;
+  flif() {}
+}
+
+main() {
+ var c = new C();
+ c.flif = 42;
+ Expect.equals('flif=', c.im.memberName);
+ Expect.equals(42, c.im.positionalArguments[0]);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 08428a2..04878b6 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -35,9 +35,6 @@
 const_init6_negative_test: Fail       # Issue 811
 super_first_constructor_test: Fail # Issue 1372.
 
-# Issue 1355
-call_operator_test: Fail
-
 parameter_initializer6_negative_test: Fail # Issue 3502
 
 named_parameters_aggregated_test/05: Fail # Compile-time error reported instead of static type warning.
@@ -52,12 +49,12 @@
 
 compile_time_constant10_test/none: Fail # issue 5214
 
-invocation_mirror_test: Fail # issue 3326, 3622.
-no_such_method_test: Fail # issue 3326, 3622.
+invocation_mirror_test: Fail # issue 3326.
+invocation_mirror_indirect_test: Fail # Issue 3326
+super_call4_test: Fail # issue 3326.
 
 export_cyclic_test: Fail, Crash # issue 6060
 duplicate_export_negative_test: Fail # issue 6134
-invocation_mirror_indirect_test: Fail # Issue 3326
 type_annotation_test/04: Fail # Issue 6970
 type_annotation_test/06: Fail # Issue 6973
 type_annotation_test/09: Fail # Issue 6973
@@ -267,6 +264,21 @@
 try_catch_syntax_test/08: Fail
 
 
+# test issue 7298 (use deprecated === and !==)
+compile_time_constant8_test: Fail
+compile_time_constant_b_test: Fail
+compile_time_constant_d_test: Fail
+compile_time_constant_e_test: Fail
+licm_test: Fail
+typed_equality_test: Fail
+
+
+# test issue 7337 (reference unknown ID from static is warning, even when with import prefix)
+prefix12_negative_test: Fail
+prefix2_negative_test: Fail
+
+
+
 #
 # Add new dartc annotations above in alphabetical order
 #
@@ -421,8 +433,6 @@
 # external keyword is not yet supported by dart2js/dart2dart.
 external_test/*: Skip
 lazy_static3_test: Fail, OK # Issue 3558
-# Call operator is not supported by DartVM (see suppression above.)
-call_operator_test: Fail
 # dart2js frontend doesn't even analyse problematic classes.
 duplicate_implements_test/01: Fail
 duplicate_implements_test/02: Fail
@@ -519,9 +529,11 @@
 type_error_test: Fail, OK # VM bug: http://dartbug.com/5280
 
 # This is a VM error when the compiled code is run.
-invocation_mirror_test: Fail # issue 3326, 3622.
-invocation_mirror_indirect_test: Fail # issue 3326, 3622.
+invocation_mirror_test: Fail # issue 3326.
+invocation_mirror_indirect_test: Fail # issue 3326.
+super_call4_test: Fail # issue 3326.
 
 [ $compiler == dart2dart && $minified ]
 import_core_prefix_test: Pass
 prefix22_test: Pass
+invocation_mirror2_test: Fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 6160c80..0c88a52 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -2,9 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-[ $compiler == dart2js && $host_checked && $checked]
-new_expression_type_args_test/02: Crash # Issue 6931
-
 [ $compiler == dart2js || $compiler == dart2dart ]
 class_literal_test/01: Fail # Class literals are expression now; delete this test.
 class_literal_test/02: Fail # Class literals are expression now; delete this test.
@@ -57,8 +54,6 @@
 factory1_test/01: Fail
 type_annotation_test/09: Fail # Named constructors interpreted as a type.
 
-super_call4_test: Fail # Badly generated noSuchMethod call.
-
 [ $compiler == dart2js && $unchecked ]
 default_factory2_test/01: Fail # type arguments on redirecting factory not implemented
 type_variable_scope_test: Fail # type arguments on redirecting factory not implemented
@@ -95,7 +90,7 @@
 new_expression_type_args_test/01: Fail # Wrongly reports compile-time error.
 double_int_to_string_test: Fail # Issue 1533 (double/integer distinction)
 mint_arithmetic_test: Fail # Issue 1533 (big integer arithmetic).
-arithmetic_test: Fail # http://dartbug.com/6627
+left_shift_test: Fail # Issue 1533
 factory_redirection_test/01: Fail
 factory_redirection_test/05: Fail
 factory_redirection_test/07: Fail
@@ -329,9 +324,6 @@
 # of failing.
 const_factory_negative_test: Crash, Fail
 
-# Implement InvocationMirror and pass it to noSuchMethod.
-invocation_mirror_test: Fail
-
 [ $compiler == dart2js && $mode == release ]
 assign_top_method_negative_test: Crash
 
@@ -354,6 +346,10 @@
 
 
 [ $compiler == dart2js && $runtime == safari ]
+execute_finally8_test: Fail # TODO(ahe): Please triage this failure.
+execute_finally9_test: Fail # TODO(ahe): Please triage this failure.
+null_access_error_test: Fail # TODO(ahe): Please triage this failure.
+string_interpolate_null_test: Fail # TODO(ahe): Please triage this failure.
 arithmetic_test: Skip # BUG(3492): Times out.
 call_through_null_getter_test: Fail # Expected: ObjectNotClosureException got: Instance of 'TypeError'
 closure3_test: Fail # Uncaught error: Instance of 'TypeError'
diff --git a/tests/language/left_shift_test.dart b/tests/language/left_shift_test.dart
new file mode 100644
index 0000000..9cca5d3
--- /dev/null
+++ b/tests/language/left_shift_test.dart
@@ -0,0 +1,11 @@
+// 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.
+
+main() {
+  for (int i = 0; i < 80; i++) {
+    var a = -1 << i;
+    var b = -1;
+    Expect.equals(1 << i, a ~/ b);
+  }
+}
diff --git a/tests/language/megamorphic_no_such_method_test.dart b/tests/language/megamorphic_no_such_method_test.dart
new file mode 100644
index 0000000..56c3287
--- /dev/null
+++ b/tests/language/megamorphic_no_such_method_test.dart
@@ -0,0 +1,64 @@
+// 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.
+// Test program for correct optimizations related to types fo allocated lists.
+
+// Classes to induce polymorphism of degree 10.
+class A0 {
+  test() => 0;
+}
+
+class A1 {
+  test() => 1;
+}
+
+class A2 {
+  test() => 2;
+}
+
+class A3 {
+  test() => 3;
+}
+
+class A4 {
+  test() => 4;
+}
+
+class A5 {
+  test() => 5;
+}
+
+class A6 {
+  test() => 6;
+}
+
+class A7 {
+  test() => 7;
+}
+
+class A8 {
+  test() => 8;
+}
+
+class A9 {
+  test() => 9;
+}
+
+// Class with no test method.
+class B { }
+
+test(obj) {
+  return obj.test(); 
+}
+
+main() {
+  // Trigger optimization of 'test' function.
+  List list = [new A0(), new A1(), new A2(), new A3(), new A4(),
+               new A5(), new A6(), new A7(), new A8(), new A9()];
+  for (int i = 0; i < 1000; i++) {
+    for (var obj in list) {
+      test(obj);
+    }
+  }
+  Expect.throws(() => test(new B()), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/super_call4_test.dart b/tests/language/super_call4_test.dart
index f5ce7c28..0093bda 100644
--- a/tests/language/super_call4_test.dart
+++ b/tests/language/super_call4_test.dart
@@ -6,8 +6,30 @@
 // current class.
 
 class C {
+  E e = new E();
+
   bool noSuchMethod(InvocationMirror im) {
-    return true;
+    if (im.memberName == 'foo') {
+      return im.positionalArguments.isEmpty &&
+             im.namedArguments.isEmpty &&
+             im.invokeOn(e);
+    }
+    if (im.memberName == 'bar') {
+      return im.positionalArguments.length == 1 &&
+             im.namedArguments.isEmpty &&
+             im.invokeOn(e);
+    }
+    if (im.memberName == 'baz') {
+      return im.positionalArguments.isEmpty &&
+             im.namedArguments.length == 1 &&
+             im.invokeOn(e);
+    }
+    if (im.memberName == 'boz') {
+      return im.positionalArguments.length == 1 &&
+             im.namedArguments.length == 1 &&
+             im.invokeOn(e);
+    }
+    return false;
   }
 }
 
@@ -15,12 +37,31 @@
   bool noSuchMethod(InvocationMirror im) {
     return false;
   }
-  test() {
+  test1() {
     return super.foo();
   }
+  test2() {
+    return super.bar(1);
+  }
+  test3() {
+    return super.baz(b: 2);
+  }
+  test4() {
+    return super.boz(1, c: 2);
+  }
+}
+
+class E {
+  bool foo() => true;
+  bool bar(int a) => a == 1;
+  bool baz({int b}) => b == 2;
+  bool boz(int a, {int c}) => a == 1 && c == 2;
 }
 
 main() {
   var d = new D();
-  Expect.isTrue(d.test());
+  Expect.isTrue(d.test1());
+  Expect.isTrue(d.test2());
+  Expect.isTrue(d.test3());
+  Expect.isTrue(d.test4());
 }
diff --git a/tests/language/syntax_test.dart b/tests/language/syntax_test.dart
index 6c6821c..462bdbd 100644
--- a/tests/language/syntax_test.dart
+++ b/tests/language/syntax_test.dart
@@ -233,6 +233,10 @@
 
     new Bad();
 
+    1 + 2 = 1; /// 63: compile-time error
+    new SyntaxTest() = 1; /// 64: compile-time error
+    futureOf(null) = 1; /// 65: compile-time error
+
   } catch (ex) {
     // Swallowing exceptions. Any error should be a compile-time error
     // which kills the current isolate.
diff --git a/tests/standalone/io/directory_error_test.dart b/tests/standalone/io/directory_error_test.dart
index cf90f91..fecb223 100644
--- a/tests/standalone/io/directory_error_test.dart
+++ b/tests/standalone/io/directory_error_test.dart
@@ -17,15 +17,10 @@
   Expect.isTrue(e.osError != null);
   Expect.isTrue(e.toString().indexOf("Creation failed") != -1);
   if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the path specified") != -1);
     Expect.equals(3, e.osError.errorCode);
   }
 
@@ -49,18 +44,11 @@
 bool checkCreateTempInNonExistentFileException(e) {
   Expect.isTrue(e is DirectoryIOException);
   Expect.isTrue(e.osError != null);
-  Expect.isTrue(e.toString().indexOf(
-      "Creation of temporary directory failed") != -1);
   if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the path specified") != -1);
     Expect.equals(3, e.osError.errorCode);
   }
 
@@ -84,16 +72,6 @@
 bool checkDeleteNonExistentFileException(e) {
   Expect.isTrue(e is DirectoryIOException);
   Expect.isTrue(e.osError != null);
-  Expect.isTrue(e.toString().indexOf("Deletion failed") != -1);
-  if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the file specified") != -1);
-  }
   // File not not found has error code 2 on all supported platforms.
   Expect.equals(2, e.osError.errorCode);
 
@@ -119,15 +97,10 @@
   Expect.isTrue(e.osError != null);
   Expect.isTrue(e.toString().indexOf("Deletion failed") != -1);
   if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the path specified") != -1);
     Expect.equals(3, e.osError.errorCode);
   }
 
@@ -153,15 +126,10 @@
   Expect.isTrue(e.osError != null);
   Expect.isTrue(e.toString().indexOf("Directory listing failed") != -1);
   if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the path specified") != -1);
     Expect.equals(3, e.osError.errorCode);
   }
 
diff --git a/tests/standalone/io/file_error_test.dart b/tests/standalone/io/file_error_test.dart
index 3c8d084..218879e 100644
--- a/tests/standalone/io/file_error_test.dart
+++ b/tests/standalone/io/file_error_test.dart
@@ -16,18 +16,8 @@
   Expect.isTrue(e is FileIOException);
   Expect.isTrue(e.osError != null);
   Expect.isTrue(e.toString().indexOf(str) != -1);
-  if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the file specified") != -1);
-  }
   // File not not found has error code 2 on all supported platforms.
   Expect.equals(2, e.osError.errorCode);
-
   return true;
 }
 
@@ -121,15 +111,10 @@
   Expect.isTrue(e.osError != null);
   Expect.isTrue(e.toString().indexOf("Cannot create file") != -1);
   if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
     Expect.equals(2, e.osError.errorCode);
   } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the path specified") != -1);
     Expect.equals(3, e.osError.errorCode);
   }
 
@@ -162,15 +147,6 @@
   Expect.isTrue(e is FileIOException);
   Expect.isTrue(e.osError != null);
   Expect.isTrue(e.toString().indexOf("Cannot retrieve full path") != -1);
-  if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the file specified") != -1);
-  }
   // File not not found has error code 2 on all supported platforms.
   Expect.equals(2, e.osError.errorCode);
 
@@ -204,15 +180,6 @@
   Expect.isTrue(e.osError != null);
   Expect.isTrue(
       e.toString().indexOf("Cannot retrieve directory for file") != -1);
-  if (Platform.operatingSystem == "linux") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "macos") {
-    Expect.isTrue(e.toString().indexOf("No such file or directory") != -1);
-  } else if (Platform.operatingSystem == "windows") {
-    Expect.isTrue(
-        e.toString().indexOf(
-            "The system cannot find the file specified") != -1);
-  }
   // File not not found has error code 2 on all supported platforms.
   Expect.equals(2, e.osError.errorCode);
 
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index 72f4d8a..dafd9f9 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -40,7 +40,7 @@
 
     void reset() {
       httpParser = new _HttpParser.requestParser();
-      httpParser.requestStart = (m, u, v, h) {
+      httpParser.requestStart = (m, u, v, h, b) {
         method = m;
         uri = u;
         version = v;
@@ -60,7 +60,7 @@
         Expect.equals(connectionClose, !httpParser.persistentConnection);
         headersCompleteCalled = true;
       };
-      httpParser.responseStart = (s, r, v, h) {
+      httpParser.responseStart = (s, r, v, h, b) {
         Expect.fail("Expected request");
       };
       httpParser.dataReceived = (List<int> data) {
@@ -126,7 +126,9 @@
 
     void reset() {
       httpParser = new _HttpParser.requestParser();
-      httpParser.responseStart = (s, r) { Expect.fail("Expected request"); };
+      httpParser.responseStart = (s, r, v, h, b) {
+        Expect.fail("Expected request");
+      };
       httpParser.error = (e) {
         errorCalled = true;
       };
@@ -185,10 +187,10 @@
       if (responseToMethod != null) {
         httpParser.responseToMethod = responseToMethod;
       }
-      httpParser.requestStart = (m, u, v, h) {
+      httpParser.requestStart = (m, u, v, h, b) {
         Expect.fail("Expected response");
       };
-      httpParser.responseStart = (s, r, v, h) {
+      httpParser.responseStart = (s, r, v, h, b) {
         statusCode = s;
         reasonPhrase = r;
         version = v;
@@ -276,7 +278,9 @@
 
     void reset() {
       httpParser = new _HttpParser.responseParser();
-      httpParser.requestStart = (m, u) => Expect.fail("Expected response");
+      httpParser.requestStart = (m, u, v, h, b) {
+        Expect.fail("Expected response");
+      };
       httpParser.error = (e) => errorCalled = true;
       httpParser.closed = () { };
 
diff --git a/tests/standalone/io/http_redirect_test.dart b/tests/standalone/io/http_redirect_test.dart
index 6bae57e..1bad27f 100644
--- a/tests/standalone/io/http_redirect_test.dart
+++ b/tests/standalone/io/http_redirect_test.dart
@@ -87,6 +87,43 @@
      }
   );
 
+  // Setup redirect for 301 where POST should not redirect.
+  server.addRequestHandler(
+     (HttpRequest request) => request.path == "/301src",
+     (HttpRequest request, HttpResponse response) {
+       Expect.equals("POST", request.method);
+       response.headers.set(HttpHeaders.LOCATION,
+                            "http://127.0.0.1:${server.port}/301target");
+       response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+       response.outputStream.close();
+     }
+  );
+  server.addRequestHandler(
+     (HttpRequest request) => request.path == "/301target",
+     (HttpRequest request, HttpResponse response) {
+       Expect.fail("Redirect of POST should not happen");
+     }
+  );
+
+  // Setup redirect for 303 where POST should turn into GET.
+  server.addRequestHandler(
+     (HttpRequest request) => request.path == "/303src",
+     (HttpRequest request, HttpResponse response) {
+       Expect.equals("POST", request.method);
+       response.headers.set(HttpHeaders.LOCATION,
+                            "http://127.0.0.1:${server.port}/303target");
+       response.statusCode = HttpStatus.SEE_OTHER;
+       response.outputStream.close();
+     }
+  );
+  server.addRequestHandler(
+     (HttpRequest request) => request.path == "/303target",
+     (HttpRequest request, HttpResponse response) {
+       Expect.equals("GET", request.method);
+       response.outputStream.close();
+     }
+  );
+
   return server;
 }
 
@@ -212,6 +249,66 @@
   conn.onError = (e) => Expect.fail("Error not expected ($e)");
 }
 
+void testAutoRedirect301POST() {
+  HttpServer server = setupServer();
+  HttpClient client = new HttpClient();
+
+  var requestCount = 0;
+
+  void onRequest(HttpClientRequest request) {
+    requestCount++;
+    request.outputStream.close();
+  };
+
+  void onResponse(HttpClientResponse response) {
+    Expect.equals(HttpStatus.MOVED_PERMANENTLY, response.statusCode);
+    response.inputStream.onData =
+        () => Expect.fail("Response data not expected");
+    response.inputStream.onClosed = () {
+      Expect.equals(1, requestCount);
+      server.close();
+      client.shutdown();
+    };
+  };
+
+  HttpClientConnection conn =
+      client.postUrl(
+          new Uri.fromString("http://127.0.0.1:${server.port}/301src"));
+  conn.onRequest = onRequest;
+  conn.onResponse = onResponse;
+  conn.onError = (e) => Expect.fail("Error not expected ($e)");
+}
+
+void testAutoRedirect303POST() {
+  HttpServer server = setupServer();
+  HttpClient client = new HttpClient();
+
+  var requestCount = 0;
+
+  void onRequest(HttpClientRequest request) {
+    requestCount++;
+    request.outputStream.close();
+  };
+
+  void onResponse(HttpClientResponse response) {
+    Expect.equals(HttpStatus.OK, response.statusCode);
+    response.inputStream.onData =
+        () => Expect.fail("Response data not expected");
+    response.inputStream.onClosed = () {
+      Expect.equals(1, requestCount);
+      server.close();
+      client.shutdown();
+    };
+  };
+
+  HttpClientConnection conn =
+      client.postUrl(
+          new Uri.fromString("http://127.0.0.1:${server.port}/303src"));
+  conn.onRequest = onRequest;
+  conn.onResponse = onResponse;
+  conn.onError = (e) => Expect.fail("Error not expected ($e)");
+}
+
 void testAutoRedirectLimit() {
   HttpServer server = setupServer();
   HttpClient client = new HttpClient();
@@ -254,6 +351,8 @@
   testManualRedirectWithHeaders();
   testAutoRedirect();
   testAutoRedirectWithHeaders();
+  testAutoRedirect301POST();
+  testAutoRedirect303POST();
   testAutoRedirectLimit();
   testRedirectLoop();
 }
diff --git a/tests/standalone/io/pkcert/cert9.db b/tests/standalone/io/pkcert/cert9.db
index 1c4913b..df2cf3e 100644
--- a/tests/standalone/io/pkcert/cert9.db
+++ b/tests/standalone/io/pkcert/cert9.db
Binary files differ
diff --git a/tests/standalone/io/pkcert/key4.db b/tests/standalone/io/pkcert/key4.db
index 6610e75..e529055 100644
--- a/tests/standalone/io/pkcert/key4.db
+++ b/tests/standalone/io/pkcert/key4.db
Binary files differ
diff --git a/tests/standalone/io/regress_7191_script.dart b/tests/standalone/io/regress_7191_script.dart
new file mode 100644
index 0000000..d90f0b5
--- /dev/null
+++ b/tests/standalone/io/regress_7191_script.dart
@@ -0,0 +1,30 @@
+// 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.
+
+import 'dart:io';
+import 'dart:isolate';
+
+main() {
+  // Open a port to make the script hang.
+  var port = new ReceivePort();
+  // Start sub-process when receiving data.
+  stdin.onData = () {
+    var data = stdin.read();
+    var options = new Options();
+    Process.start(options.executable, [options.script]).then((p) {
+      p.stdout.onData = p.stdout.read;
+      p.stderr.onData = p.stderr.read;
+      // When receiving data again, kill sub-process and exit.
+      stdin.onData = () {
+        var data = stdin.read();
+        Expect.listEquals([0], data);
+        p.kill();
+        p.onExit = exit;
+      };
+      // Close stdout. If handles are incorrectly inherited this will
+      // not actually close stdout and the test will hang.
+      stdout.close();
+    });
+  };
+}
diff --git a/tests/standalone/io/regress_7191_test.dart b/tests/standalone/io/regress_7191_test.dart
new file mode 100644
index 0000000..75284be
--- /dev/null
+++ b/tests/standalone/io/regress_7191_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+// Regression test for http://dartbug.com/7191.
+
+// Starts a sub-process which in turn starts another sub-process and then closes
+// its standard output. If handles are incorrectly inherited on Windows, this
+// will lead to a situation where the stdout of the first sub-process is never
+// closed which will make this test hang.
+
+import 'dart:io';
+import 'dart:isolate';
+
+main() {
+  var port = new ReceivePort();
+  var options = new Options();
+  var executable = options.executable;
+  var scriptDir = new Path.fromNative(options.script).directoryPath;
+  var script = scriptDir.append('regress_7191_script.dart').toNativePath();
+  Process.start(executable, [script]).then((process) {
+    process.stdin.write([0]);
+    process.stdout.onData = process.stdout.read;
+    process.stderr.onData = process.stderr.read;
+    process.stdout.onClosed = () {
+      process.stdin.write([0]);
+    };
+    process.onExit = (exitCode) => port.close();
+  });
+}
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
new file mode 100644
index 0000000..261c716
--- /dev/null
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -0,0 +1,125 @@
+// 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.
+
+import "dart:io";
+import "dart:isolate";
+
+const SERVER_ADDRESS = "127.0.0.1";
+const HOST_NAME = "localhost";
+
+void WriteAndClose(Socket socket, String message) {
+  var data = message.charCodes;
+  int written = 0;
+  void write() {
+    written += socket.writeList(data, written, data.length - written);
+    if (written < data.length) {
+      socket.onWrite = write;
+    } else {
+      socket.close(true);
+    }
+  }
+  write();
+}
+
+class SecureTestServer {
+  void onConnection(Socket connection) {
+    connection.onConnect = () {
+      numConnections++;
+      var certificate = connection.peerCertificate;
+      Expect.isTrue(certificate.subject.contains("CN="));
+    };
+    String received = "";
+    connection.onData = () {
+      received = received.concat(new String.fromCharCodes(connection.read()));
+    };
+    connection.onClosed = () {
+      Expect.isTrue(received.contains("Hello from client "));
+      String name = received.substring(received.indexOf("client ") + 7);
+      WriteAndClose(connection, "Welcome, client $name");
+    };
+  }
+
+  void errorHandlerServer(Exception e) {
+    Expect.fail("Server socket error $e");
+  }
+
+  int start() {
+    server = new SecureServerSocket(SERVER_ADDRESS,
+                                    0,
+                                    10,
+                                    "CN=$HOST_NAME",
+                                    requireClientCertificate: true);
+    Expect.isNotNull(server);
+    server.onConnection = onConnection;
+    server.onError = errorHandlerServer;
+    return server.port;
+  }
+
+  void stop() {
+    server.close();
+  }
+
+  int numConnections = 0;
+  SecureServerSocket server;
+}
+
+class SecureTestClient {
+  SecureTestClient(int this.port, String this.name) {
+    socket = new SecureSocket(HOST_NAME, port, sendClientCertificate: true);
+    socket.onConnect = this.onConnect;
+    socket.onData = () {
+      reply = reply.concat(new String.fromCharCodes(socket.read()));
+    };
+    socket.onClosed = done;
+    reply = "";
+  }
+
+  void onConnect() {
+    numRequests++;
+    WriteAndClose(socket, "Hello from client $name");
+  }
+
+  void done() {
+    Expect.equals("Welcome, client $name", reply);
+    numReplies++;
+    if (numReplies == CLIENT_NAMES.length) {
+      Expect.equals(numRequests, numReplies);
+      EndTest();
+    }
+  }
+
+  static int numRequests = 0;
+  static int numReplies = 0;
+
+  int port;
+  String name;
+  SecureSocket socket;
+  String reply;
+}
+
+Function EndTest;
+
+const CLIENT_NAMES = const ['able', 'baker', 'camera', 'donut', 'echo'];
+
+void main() {
+  ReceivePort keepAlive = new ReceivePort();
+  Path scriptDir = new Path.fromNative(new Options().script).directoryPath;
+  Path certificateDatabase = scriptDir.append('pkcert');
+  SecureSocket.initialize(database: certificateDatabase.toNativePath(),
+                          password: 'dartdart',
+                          useBuiltinRoots: false);
+
+  var server = new SecureTestServer();
+  int port = server.start();
+
+  EndTest = () {
+    Expect.equals(CLIENT_NAMES.length, server.numConnections);
+    server.stop();
+    keepAlive.close();
+  };
+
+  for (var x in CLIENT_NAMES) {
+    new SecureTestClient(port, x);
+  }
+}
diff --git a/tests/standalone/io/secure_server_test.dart b/tests/standalone/io/secure_server_test.dart
index 8941548..d27ca9a 100644
--- a/tests/standalone/io/secure_server_test.dart
+++ b/tests/standalone/io/secure_server_test.dart
@@ -101,7 +101,8 @@
   Path scriptDir = new Path.fromNative(new Options().script).directoryPath;
   Path certificateDatabase = scriptDir.append('pkcert');
   SecureSocket.initialize(database: certificateDatabase.toNativePath(),
-                          password: 'dartdart');
+                          password: 'dartdart',
+                          useBuiltinRoots: false);
 
   var server = new SecureTestServer();
   int port = server.start();
diff --git a/tests/standalone/io/secure_session_resume_test.dart b/tests/standalone/io/secure_session_resume_test.dart
new file mode 100644
index 0000000..825351a
--- /dev/null
+++ b/tests/standalone/io/secure_session_resume_test.dart
@@ -0,0 +1,134 @@
+// 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.
+
+// This test tests TLS session resume, by making multiple client connections
+// on the same port to the same server, with a delay of 200 ms between them.
+// The unmodified secure_server_test creates all sessions simultaneously,
+// which means that no handshake completes and caches its keys in the session
+// cache in time for other connections to use it.
+//
+// Session resume is currently disabled - see issue
+// https://code.google.com/p/dart/issues/detail?id=7230
+
+import "dart:io";
+import "dart:isolate";
+
+const SERVER_ADDRESS = "127.0.0.1";
+const HOST_NAME = "localhost";
+
+void WriteAndClose(Socket socket, String message) {
+  var data = message.charCodes;
+  int written = 0;
+  void write() {
+    written += socket.writeList(data, written, data.length - written);
+    if (written < data.length) {
+      socket.onWrite = write;
+    } else {
+      socket.close(true);
+    }
+  }
+  write();
+}
+
+class SecureTestServer {
+  void onConnection(Socket connection) {
+    connection.onConnect = () {
+      numConnections++;
+    };
+    String received = "";
+    connection.onData = () {
+      received = received.concat(new String.fromCharCodes(connection.read()));
+    };
+    connection.onClosed = () {
+      Expect.isTrue(received.contains("Hello from client "));
+      String name = received.substring(received.indexOf("client ") + 7);
+      WriteAndClose(connection, "Welcome, client $name");
+    };
+  }
+
+  void errorHandlerServer(Exception e) {
+    Expect.fail("Server socket error $e");
+  }
+
+  int start() {
+    server = new SecureServerSocket(SERVER_ADDRESS, 0, 10, "CN=$HOST_NAME");
+    Expect.isNotNull(server);
+    server.onConnection = onConnection;
+    server.onError = errorHandlerServer;
+    return server.port;
+  }
+
+  void stop() {
+    server.close();
+  }
+
+  int numConnections = 0;
+  SecureServerSocket server;
+}
+
+class SecureTestClient {
+  SecureTestClient(int this.port, String this.name) {
+    socket = new SecureSocket(HOST_NAME, port);
+    socket.onConnect = this.onConnect;
+    socket.onData = () {
+      reply = reply.concat(new String.fromCharCodes(socket.read()));
+    };
+    socket.onClosed = done;
+    reply = "";
+  }
+
+  void onConnect() {
+    numRequests++;
+    WriteAndClose(socket, "Hello from client $name");
+  }
+
+  void done() {
+    Expect.equals("Welcome, client $name", reply);
+    numReplies++;
+    if (numReplies == CLIENT_NAMES.length) {
+      Expect.equals(numRequests, numReplies);
+      EndTest();
+    }
+  }
+
+  static int numRequests = 0;
+  static int numReplies = 0;
+
+  int port;
+  String name;
+  SecureSocket socket;
+  String reply;
+}
+
+Function EndTest;
+
+const CLIENT_NAMES = const ['able', 'baker'];
+
+void main() {
+  ReceivePort keepAlive = new ReceivePort();
+  Path scriptDir = new Path.fromNative(new Options().script).directoryPath;
+  Path certificateDatabase = scriptDir.append('pkcert');
+  SecureSocket.initialize(database: certificateDatabase.toNativePath(),
+                          password: 'dartdart',
+                          useBuiltinRoots: false);
+
+  var server = new SecureTestServer();
+  int port = server.start();
+
+  EndTest = () {
+    Expect.equals(CLIENT_NAMES.length, server.numConnections);
+    server.stop();
+    keepAlive.close();
+  };
+
+  int delay = 0;
+  int delay_between_connections = 300;  // Milliseconds.
+
+  for (var x in CLIENT_NAMES) {
+    new Timer(delay, (_) {
+      new SecureTestClient(port, x);
+    });
+    delay += delay_between_connections;
+  }
+}
diff --git a/tests/standalone/io/windows_environment_script.dart b/tests/standalone/io/windows_environment_script.dart
new file mode 100644
index 0000000..d94a52c
--- /dev/null
+++ b/tests/standalone/io/windows_environment_script.dart
@@ -0,0 +1,12 @@
+// 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.
+
+#import("dart:io");
+
+main() {
+  var scriptDir = Platform.environment['SCRIPTDIR'];
+  Expect.isTrue(scriptDir.contains('å'));
+  var str = new File('$scriptDir/funky.bat').readAsStringSync();
+  Expect.isTrue(str.contains('%~dp0'));
+}
diff --git a/tests/standalone/io/windows_environment_test.dart b/tests/standalone/io/windows_environment_test.dart
new file mode 100644
index 0000000..34dc2a2
--- /dev/null
+++ b/tests/standalone/io/windows_environment_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+#import("dart:io");
+
+main() {
+  if (Platform.operatingSystem != 'windows') return;
+  var tempDir = new Directory('').createTempSync();
+  var funkyDir = new Directory("${tempDir.path}/å");
+  funkyDir.createSync();
+  var funkyFile = new File('${funkyDir.path}/funky.bat');
+  funkyFile.writeAsStringSync("""
+@echo off
+set SCRIPTDIR=%~dp0
+%1 %2
+      """);
+  var options = new Options();
+  var dart = options.executable;
+  var scriptDir = new Path.fromNative(options.script).directoryPath;
+  var script = scriptDir.append('windows_environment_script.dart');
+  Process.run('cmd',
+              ['/c', funkyFile.name, dart, script.toNativePath()]).then((p) {
+    Expect.equals(0, p.exitCode);
+    tempDir.deleteSync(recursive: true);
+  });
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 1e89cdb..fa225d4 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -23,7 +23,6 @@
 # This is expected as MacOS by default runs with a very low number
 # of allowed open files ('ulimit -n' says something like 256).
 io/socket_many_connections_test: Skip
-io/http_auth_test: Skip  # Issue 7183
 
 # These tests pass on MacOS 10.8.2 but fails on the buildbot machines
 # that are running an earlier version of MacOS. The issue is that the
@@ -42,7 +41,8 @@
 io/secure_server_stream_test: Pass, Crash, Timeout  # Issue 6893
 io/secure_server_test: Pass, Crash, Fail, Timeout  # Issue 6893
 io/secure_no_builtin_roots_test: Pass, Crash  # Issue 7157
-io/secure_socket_bad_certificate_test: Pass, Crash, Timeout  # Issue 7157
+io/secure_socket_bad_certificate_test: Pass, Crash, Fail, Timeout  # Issue 7157
+io/http_shutdown_test: Pass, Fail, Timeout  # Issue 7294
 
 [ $compiler == none && $runtime == drt ]
 io/*: Skip # Don't run tests using dart:io in the browser
diff --git a/tests/utils/dart2js_test.dart b/tests/utils/dart2js_test.dart
new file mode 100644
index 0000000..f7786fb
--- /dev/null
+++ b/tests/utils/dart2js_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// Test to ensure that dart2js is free of warnings.
+
+// Test annotation to let the test framework know that this file
+// should analyze without any warnings.
+// @static-clean
+
+import '../../sdk/lib/_internal/compiler/implementation/dart2js.dart'
+    as dart2js;
+
+void main() {
+  // Do nothing.
+}
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index af4c06a..cd329ca 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -4,6 +4,8 @@
 
 // Smoke test of the dart2js compiler API.
 
+library dummy_compiler;
+
 import '../../sdk/lib/_internal/compiler/compiler.dart';
 import 'dart:uri';
 
@@ -14,7 +16,7 @@
     source = "main() {}";
   } else if (uri.scheme == "lib") {
     if (uri.path.endsWith("/core.dart")) {
-      source = """#library('core');
+      source = """library core;
                   class Object {}
                   class Type {}
                   class bool {}
@@ -36,11 +38,19 @@
       source = '';
     } else if (uri.path.endsWith('interceptors.dart')) {
       source = """class ObjectInterceptor {}
+                  class JSArray {}
+                  class JSString {}
+                  class JSFunction {}
+                  class JSInt {}
+                  class JSDouble {}
+                  class JSNumber {}
+                  class JSNull {}
+                  class JSBool {}
                   var getInterceptor;""";
     } else if (uri.path.endsWith('js_helper.dart')) {
       source = 'library jshelper; class JSInvocationMirror {}';
     } else {
-      source = "#library('lib');";
+      source = "library lib;";
     }
   } else {
    throw "unexpected URI $uri";
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index d8b095d..e421ea3 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -10,8 +10,9 @@
 recursive_import_test: Slow, Pass
 
 [ $compiler == none && $runtime == drt ]
-dummy_compiler_test: Fail # http://dartbug.com/2264
+dummy_compiler_test: Skip # http://dartbug.com/7233
 recursive_import_test: Fail # http://dartbug.com/2264
+dart2js_test: Fail # http://dartbug.com/2264
 
 [ $compiler == dart2js && $browser ]
 *: Skip
@@ -27,6 +28,3 @@
 *: Skip
 
 [ $compiler == dartc ]
-# dart2js issue 6870
-dummy_compiler_test: Fail, OK
-recursive_import_test: Fail, OK
diff --git a/tools/VERSION b/tools/VERSION
index 3c41a1a..0ade99d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 2
-BUILD 8
-PATCH 2
+BUILD 9
+PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index c752f8d..9e88f2c 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -99,7 +99,7 @@
   flags = [x for x in flags if not '=' in x]
   return ('%s tests %s' % (name, ' '.join(flags))).strip()
 
-
+IsFirstTestStepCall = True
 def TestStep(name, mode, system, compiler, runtime, targets, flags):
   step_name = TestStepName(name, flags)
   with bot.BuildStep(step_name, swallow_error=True):
@@ -121,11 +121,21 @@
                 '--use-sdk',
                 '--report'])
 
+    # TODO(ricow/kustermann): Issue 7339
+    if runtime == "safari":
+      cmd.append('--nobatch')
+
     if user_test == 'yes':
       cmd.append('--progress=color')
     else:
       cmd.extend(['--progress=buildbot', '-v'])
 
+    global IsFirstTestStepCall
+    if IsFirstTestStepCall:
+      IsFirstTestStepCall = False
+    else:
+      cmd.append('--append_flaky_log')
+
     if flags:
       cmd.extend(flags)
     cmd.extend(targets)
diff --git a/tools/touch_version.py b/tools/touch_version.py
deleted file mode 100644
index 98841fe..0000000
--- a/tools/touch_version.py
+++ /dev/null
@@ -1,18 +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.
-#
-# This python script "touches" the tools/VERSION file.
-
-import os
-import sys
-
-# Change into the dart directory as we want to be able to access the VERSION file
-# from a simple path.
-runtime_src = os.path.join(os.path.dirname(sys.argv[0]), os.pardir)
-os.chdir(runtime_src)
-
-if __name__ == '__main__':
-  print 'Touching tools/VERSION.'
-  os.utime(os.path.join('tools', 'VERSION'), None)
-  sys.exit(0)
diff --git a/utils/pub/command_help.dart b/utils/pub/command_help.dart
index 7681f37..33ef705 100644
--- a/utils/pub/command_help.dart
+++ b/utils/pub/command_help.dart
@@ -7,11 +7,12 @@
 import 'dart:io' as io;
 import 'exit_codes.dart' as exit_codes;
 import 'io.dart';
+import 'log.dart' as log;
 import 'pub.dart';
 
 /** Handles the `help` pub command. */
 class HelpCommand extends PubCommand {
-  String get description => "display help information for Pub";
+  String get description => "Display help information for Pub.";
   String get usage => 'pub help [command]';
   bool get requiresEntrypoint => false;
 
@@ -22,8 +23,8 @@
       var name = commandOptions.rest[0];
       var command = pubCommands[name];
       if (command == null) {
-        printError('Could not find a command named "$name".');
-        printError('Run "pub help" to see available commands.');
+        log.error('Could not find a command named "$name".');
+        log.error('Run "pub help" to see available commands.');
         io.exit(exit_codes.USAGE);
       }
 
diff --git a/utils/pub/command_install.dart b/utils/pub/command_install.dart
index c14884e2..e5188f6 100644
--- a/utils/pub/command_install.dart
+++ b/utils/pub/command_install.dart
@@ -5,16 +5,17 @@
 library command_install;
 
 import 'entrypoint.dart';
+import 'log.dart' as log;
 import 'pub.dart';
 
 /** Handles the `install` pub command. */
 class InstallCommand extends PubCommand {
-  String get description => "install the current package's dependencies";
+  String get description => "Install the current package's dependencies.";
   String get usage => "pub install";
 
   Future onRun() {
     return entrypoint.installDependencies().transform((_) {
-      print("Dependencies installed!");
+      log.message("Dependencies installed!");
     });
   }
 }
diff --git a/utils/pub/command_lish.dart b/utils/pub/command_lish.dart
index 3895232..f775b46 100644
--- a/utils/pub/command_lish.dart
+++ b/utils/pub/command_lish.dart
@@ -10,17 +10,16 @@
 
 import '../../pkg/args/lib/args.dart';
 import '../../pkg/http/lib/http.dart' as http;
-import 'pub.dart';
-import 'io.dart';
 import 'git.dart' as git;
+import 'io.dart';
+import 'log.dart' as log;
 import 'oauth2.dart' as oauth2;
+import 'pub.dart';
 import 'validator.dart';
 
-// TODO(nweiz): Make "publish" the primary name for this command. See issue
-// 6949.
 /// Handles the `lish` and `publish` pub commands.
 class LishCommand extends PubCommand {
-  final description = "publish the current package to pub.dartlang.org";
+  final description = "Publish the current package to pub.dartlang.org.";
   final usage = "pub publish [options]";
   final aliases = const ["lish", "lush"];
 
@@ -42,6 +41,7 @@
       return Futures.wait([
         client.get(server.resolve("/packages/versions/new.json")),
         _filesToPublish.transform((files) {
+          log.fine('Archiving and publishing ${entrypoint.root}.');
           return createTarGz(files, baseDir: entrypoint.root.dir);
         }).chain(consumeInputStream),
         _validate()
@@ -77,7 +77,7 @@
             parsed['success']['message'] is! String) {
           _invalidServerResponse(response);
         }
-        print(parsed['success']['message']);
+        log.message(parsed['success']['message']);
       });
     }).transformException((e) {
       if (e is PubHttpException) {
@@ -97,13 +97,13 @@
           throw errorMap['error']['message'];
         }
       } else if (e is oauth2.ExpirationException) {
-        printError("Pub's authorization to upload packages has expired and "
+        log.error("Pub's authorization to upload packages has expired and "
             "can't be automatically refreshed.");
         return onRun();
       } else if (e is oauth2.AuthorizationException) {
         var message = "OAuth2 authorization failed";
         if (e.description != null) message = "$message (${e.description})";
-        printError("$message.");
+        log.error("$message.");
         return oauth2.clearCredentials(cache).chain((_) => onRun());
       } else {
         throw e;
@@ -142,9 +142,8 @@
       if (file == null || _BLACKLISTED_FILES.contains(basename(file))) {
         return false;
       }
-      // TODO(nweiz): Since `file` is absolute, this will break if the package
-      // itself is in a directory named "packages" (issue 7215).
-      return !splitPath(file).some(_BLACKLISTED_DIRECTORIES.contains);
+      return !splitPath(relativeTo(file, rootDir))
+          .some(_BLACKLISTED_DIRECTORIES.contains);
     }));
   }
 
diff --git a/utils/pub/command_update.dart b/utils/pub/command_update.dart
index 16155e2..6995a6d 100644
--- a/utils/pub/command_update.dart
+++ b/utils/pub/command_update.dart
@@ -5,12 +5,13 @@
 library command_update;
 
 import 'entrypoint.dart';
+import 'log.dart' as log;
 import 'pub.dart';
 
 /** Handles the `update` pub command. */
 class UpdateCommand extends PubCommand {
   String get description =>
-    "update the current package's dependencies to the latest versions";
+    "Update the current package's dependencies to the latest versions.";
 
   String get usage => 'pub update [dependencies...]';
 
@@ -21,6 +22,6 @@
     } else {
       future = entrypoint.updateDependencies(commandOptions.rest);
     }
-    return future.transform((_) => print("Dependencies updated!"));
+    return future.transform((_) => log.message("Dependencies updated!"));
   }
 }
diff --git a/utils/pub/command_version.dart b/utils/pub/command_version.dart
index 464d1a2..5e2f005 100644
--- a/utils/pub/command_version.dart
+++ b/utils/pub/command_version.dart
@@ -8,7 +8,7 @@
 
 /** Handles the `version` pub command. */
 class VersionCommand extends PubCommand {
-  String get description => 'print Pub version';
+  String get description => 'Print pub version.';
   String get usage => 'pub version';
   bool get requiresEntrypoint => false;
 
diff --git a/utils/pub/curl_client.dart b/utils/pub/curl_client.dart
index e1afc2d..6922b82 100644
--- a/utils/pub/curl_client.dart
+++ b/utils/pub/curl_client.dart
@@ -8,6 +8,7 @@
 
 import '../../pkg/http/lib/http.dart' as http;
 import 'io.dart';
+import 'log.dart' as log;
 import 'utils.dart';
 
 /// A drop-in replacement for [http.Client] that uses the `curl` command-line
@@ -30,12 +31,15 @@
 
   /// Sends a request via `curl` and returns the response.
   Future<http.StreamedResponse> send(http.BaseRequest request) {
+    log.fine("Sending Curl request $request");
+
     var requestStream = request.finalize();
     return withTempDir((tempDir) {
-      var headerFile = new Path(tempDir).append("curl-headers").toNativePath();
+      var headerFile = join(tempDir, "curl-headers");
       var arguments = _argumentsForRequest(request, headerFile);
+      log.process(executable, arguments);
       var process;
-      return Process.start(executable, arguments).chain((process_) {
+      return startProcess(executable, arguments).chain((process_) {
         process = process_;
         if (requestStream.closed) {
           process.stdin.close();
@@ -114,6 +118,8 @@
   Future _waitForHeaders(Process process, {bool expectBody}) {
     var completer = new Completer();
     process.onExit = (exitCode) {
+      log.io("Curl process exited with code $exitCode.");
+
       if (exitCode == 0) {
         completer.complete(null);
         return;
@@ -122,6 +128,7 @@
       chainToCompleter(consumeInputStream(process.stderr)
             .transform((stderrBytes) {
         var message = new String.fromCharCodes(stderrBytes);
+        log.fine('Got error reading headers from curl: $message');
         if (exitCode == 47) {
           throw new RedirectLimitExceededException([]);
         } else {
diff --git a/utils/pub/entrypoint.dart b/utils/pub/entrypoint.dart
index d3af1fa..56007e0 100644
--- a/utils/pub/entrypoint.dart
+++ b/utils/pub/entrypoint.dart
@@ -6,12 +6,13 @@
 
 import 'io.dart';
 import 'lock_file.dart';
+import 'log.dart' as log;
 import 'package.dart';
 import 'root_source.dart';
 import 'system_cache.dart';
+import 'utils.dart';
 import 'version.dart';
 import 'version_solver.dart';
-import 'utils.dart';
 
 /**
  * Pub operates over a directed graph of dependencies that starts at a root
@@ -87,6 +88,7 @@
       if (!exists) return new Future.immediate(null);
       // TODO(nweiz): figure out when to actually delete the directory, and when
       // we can just re-use the existing symlink.
+      log.fine("Deleting package directory for ${id.name} before install.");
       return deleteDir(packageDir);
     }).chain((_) {
       if (id.source.shouldCache) {
@@ -165,26 +167,18 @@
    * warning message and act as though the file doesn't exist.
    */
   Future<LockFile> _loadLockFile() {
-    var completer = new Completer<LockFile>();
     var lockFilePath = join(root.dir, 'pubspec.lock');
-    var future = readTextFile(lockFilePath);
 
-    future.handleException((_) {
-      // If we failed to load the lockfile but it does exist, something's
-      // probably wrong and we should notify the user.
-      fileExists(lockFilePath).transform((exists) {
-        if (!exists) return;
-        printError("Error reading pubspec.lock: ${future.exception}");
-      }).then((_) {
-        completer.complete(new LockFile.empty());
-      });
+    log.fine("Loading lockfile.");
+    return fileExists(lockFilePath).chain((exists) {
+      if (!exists) {
+        log.fine("No lock file at $lockFilePath, creating empty one.");
+        return new Future<LockFile>.immediate(new LockFile.empty());
+      }
 
-      return true;
+      return readTextFile(lockFilePath).transform((text) =>
+          new LockFile.parse(text, cache.sources));
     });
-
-    future.then((text) =>
-        completer.complete(new LockFile.parse(text, cache.sources)));
-    return completer.future;
   }
 
   /**
@@ -196,7 +190,9 @@
       if (id.source is! RootSource) lockFile.packages[id.name] = id;
     }
 
-    return writeTextFile(join(root.dir, 'pubspec.lock'), lockFile.serialize());
+    var lockFilePath = join(root.dir, 'pubspec.lock');
+    log.fine("Saving lockfile.");
+    return writeTextFile(lockFilePath, lockFile.serialize());
   }
 
   /**
diff --git a/utils/pub/git.dart b/utils/pub/git.dart
index 80901a9..6defde3 100644
--- a/utils/pub/git.dart
+++ b/utils/pub/git.dart
@@ -8,6 +8,7 @@
 library git;
 
 import 'io.dart';
+import 'log.dart' as log;
 import 'utils.dart';
 
 /// Tests whether or not the git command-line app is available for use.
@@ -57,6 +58,7 @@
       return null;
     });
   }).transform((command) {
+    log.fine('Determined git command $command.');
     _gitCommandCache = command;
     return command;
   });
diff --git a/utils/pub/hosted_source.dart b/utils/pub/hosted_source.dart
index 8315acd..ba5119d 100644
--- a/utils/pub/hosted_source.dart
+++ b/utils/pub/hosted_source.dart
@@ -11,6 +11,7 @@
 // TODO(nweiz): Make this import better.
 import '../../pkg/http/lib/http.dart' as http;
 import 'io.dart';
+import 'log.dart' as log;
 import 'package.dart';
 import 'pubspec.dart';
 import 'source.dart';
@@ -73,7 +74,7 @@
 
     var fullUrl = "$url/packages/$name/versions/${id.version}.tar.gz";
 
-    print('Downloading $id...');
+    log.message('Downloading $id...');
 
     // Download and extract the archive to a temp directory.
     var tempDir;
diff --git a/utils/pub/io.dart b/utils/pub/io.dart
index 968f354..0ecc7b2 100644
--- a/utils/pub/io.dart
+++ b/utils/pub/io.dart
@@ -13,83 +13,50 @@
 
 // TODO(nweiz): Make this import better.
 import '../../pkg/http/lib/http.dart' as http;
-import 'utils.dart';
 import 'curl_client.dart';
+import 'log.dart' as log;
+import 'path.dart' as path;
+import 'utils.dart';
 
 bool _isGitInstalledCache;
 
 /// The cached Git command.
 String _gitCommandCache;
 
-/** Gets the current working directory. */
-String get currentWorkingDir => new File('.').fullPathSync();
-
 final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?");
 
 /**
- * Prints the given string to `stderr` on its own line.
- */
-void printError(value) {
-  stderr.writeString(value.toString());
-  stderr.writeString('\n');
-}
-
-
-/**
  * Joins a number of path string parts into a single path. Handles
  * platform-specific path separators. Parts can be [String], [Directory], or
  * [File] objects.
  */
 String join(part1, [part2, part3, part4]) {
-  final parts = sanitizePath(part1).split('/');
+  part1 = _getPath(part1);
+  if (part2 != null) part2 = _getPath(part2);
+  if (part3 != null) part3 = _getPath(part3);
+  if (part4 != null) part4 = _getPath(part4);
 
-  for (final part in [part2, part3, part4]) {
-    if (part == null) continue;
-
-    for (final piece in _getPath(part).split('/')) {
-      if (piece == '..' && parts.length > 0 &&
-          parts.last != '.' && parts.last != '..') {
-        parts.removeLast();
-      } else if (piece != '') {
-        if (parts.length > 0 && parts.last == '.') {
-          parts.removeLast();
-        }
-        parts.add(piece);
-      }
-    }
-  }
-
-  return Strings.join(parts, Platform.pathSeparator);
-}
-
-/// Splits [path] into its individual components.
-List<String> splitPath(path) => sanitizePath(path).split('/');
-
-/**
- * Gets the basename, the file name without any leading directory path, for
- * [file], which can either be a [String], [File], or [Directory].
- */
-// TODO(rnystrom): Copied from file_system (so that we don't have to add
-// file_system to the SDK). Should unify.
-String basename(file) {
-  file = sanitizePath(file);
-
-  int lastSlash = file.lastIndexOf('/', file.length);
-  if (lastSlash == -1) {
-    return file;
+  // TODO(nweiz): Don't use "?part" in path.dart.
+  if (part4 != null) {
+    return path.join(part1, part2, part3, part4);
+  } else if (part3 != null) {
+    return path.join(part1, part2, part3);
+  } else if (part2 != null) {
+    return path.join(part1, part2);
   } else {
-    return file.substring(lastSlash + 1);
+    return path.join(part1);
   }
 }
 
-/**
- * Gets the the leading directory path for [file], which can either be a
- * [String], [File], or [Directory].
- */
-// TODO(nweiz): Copied from file_system (so that we don't have to add
-// file_system to the SDK). Should unify.
+/// Gets the basename, the file name without any leading directory path, for
+/// [file], which can either be a [String], [File], or [Directory].
+String basename(file) => path.basename(_getPath(file));
+
+// TODO(nweiz): move this into path.dart.
+/// Gets the the leading directory path for [file], which can either be a
+/// [String], [File], or [Directory].
 String dirname(file) {
-  file = sanitizePath(file);
+  file = _sanitizePath(file);
 
   int lastSlash = file.lastIndexOf('/', file.length);
   if (lastSlash == -1) {
@@ -99,10 +66,21 @@
   }
 }
 
+// TODO(nweiz): move this into path.dart.
+/// Splits [path] into its individual components.
+List<String> splitPath(path) => _sanitizePath(path).split('/');
+
 /// Returns whether or not [entry] is nested somewhere within [dir]. This just
 /// performs a path comparison; it doesn't look at the actual filesystem.
-bool isBeneath(entry, dir) =>
-  sanitizePath(entry).startsWith('${sanitizePath(dir)}/');
+bool isBeneath(entry, dir) {
+  var relative = relativeTo(entry, dir);
+  return !path.isAbsolute(relative) && splitPath(relative)[0] != '..';
+}
+
+// TODO(nweiz): move this into path.dart.
+/// Returns the path to [target] from [base].
+String relativeTo(target, base) =>
+  new path.Builder(root: base).relative(target);
 
 /**
  * Asynchronously determines if [path], which can be a [String] file path, a
@@ -122,7 +100,10 @@
  * the result.
  */
 Future<bool> fileExists(file) {
-  return new File(_getPath(file)).exists();
+  var path = _getPath(file);
+  return log.ioAsync("Seeing if file $path exists.",
+      new File(path).exists(),
+      (exists) => "File $path ${exists ? 'exists' : 'does not exist'}.");
 }
 
 /**
@@ -130,7 +111,17 @@
  * a [File].
  */
 Future<String> readTextFile(file) {
-  return new File(_getPath(file)).readAsString(Encoding.UTF_8);
+  var path = _getPath(file);
+  return log.ioAsync("Reading text file $path.",
+      new File(path).readAsString(Encoding.UTF_8),
+      (contents) {
+        // Sanity check: don't spew a huge file.
+        if (contents.length < 1024 * 1024) {
+          return "Read $path. Contents:\n$contents";
+        } else {
+          return "Read ${contents.length} characters from $path.";
+        }
+      });
 }
 
 /**
@@ -138,10 +129,21 @@
  * [contents] to it. Completes when the file is written and closed.
  */
 Future<File> writeTextFile(file, String contents) {
-  file = new File(_getPath(file));
+  var path = _getPath(file);
+  file = new File(path);
+
+  // Sanity check: don't spew a huge file.
+  log.io("Writing ${contents.length} characters to text file $path.");
+  if (contents.length < 1024 * 1024) {
+    log.fine("Contents:\n$contents");
+  }
+
   return file.open(FileMode.WRITE).chain((opened) {
     return opened.writeString(contents).chain((ignore) {
-        return opened.close().transform((ignore) => file);
+        return opened.close().transform((_) {
+          log.fine("Wrote text file $path.");
+          return file;
+        });
     });
   });
 }
@@ -151,7 +153,9 @@
  * [Future] that completes when the deletion is done.
  */
 Future<File> deleteFile(file) {
-  return new File(_getPath(file)).delete();
+  var path = _getPath(file);
+  return log.ioAsync("delete file $path",
+      new File(path).delete());
 }
 
 /// Writes [stream] to a new file at [path], which may be a [String] or a
@@ -160,12 +164,15 @@
 Future<File> createFileFromStream(InputStream stream, path) {
   path = _getPath(path);
 
+  log.io("Creating $path from stream.");
+
   var completer = new Completer<File>();
   var file = new File(path);
   var outputStream = file.openOutputStream();
   stream.pipe(outputStream);
 
   outputStream.onClosed = () {
+    log.fine("Created $path from stream.");
     completer.complete(file);
   };
 
@@ -178,7 +185,11 @@
   }
 
   completeError(error) {
-    if (!completer.isComplete) completer.completeException(error, stackTrace);
+    if (!completer.isComplete) {
+      completer.completeException(error, stackTrace);
+    } else {
+      log.fine("Got error after stream was closed: $error");
+    }
   }
 
   stream.onError = completeError;
@@ -193,7 +204,8 @@
  */
 Future<Directory> createDir(dir) {
   dir = _getDirectory(dir);
-  return dir.create();
+  return log.ioAsync("create directory ${dir.path}",
+      dir.create());
 }
 
 /**
@@ -203,10 +215,15 @@
  */
 Future<Directory> ensureDir(path) {
   path = _getPath(path);
+  log.fine("Ensuring directory $path exists.");
   if (path == '.') return new Future.immediate(new Directory('.'));
 
   return dirExists(path).chain((exists) {
-    if (exists) return new Future.immediate(new Directory(path));
+    if (exists) {
+      log.fine("Directory $path already exists.");
+      return new Future.immediate(new Directory(path));
+    }
+
     return ensureDir(dirname(path)).chain((_) {
       var completer = new Completer<Directory>();
       var future = createDir(path);
@@ -214,7 +231,10 @@
         if (error is! DirectoryIOException) return false;
         // Error 17 means the directory already exists (or 183 on Windows).
         if (error.osError.errorCode != 17 &&
-            error.osError.errorCode != 183) return false;
+            error.osError.errorCode != 183) {
+          log.fine("Got 'already exists' error when creating directory.");
+          return false;
+        }
 
         completer.complete(_getDirectory(path));
         return true;
@@ -233,7 +253,8 @@
  */
 Future<Directory> createTempDir([dir = '']) {
   dir = _getDirectory(dir);
-  return dir.createTemp();
+  return log.ioAsync("create temp directory ${dir.path}",
+      dir.createTemp());
 }
 
 /**
@@ -242,7 +263,9 @@
  */
 Future<Directory> deleteDir(dir) {
   dir = _getDirectory(dir);
-  return dir.delete(recursive: true);
+
+  return _attemptRetryable(() => log.ioAsync("delete directory ${dir.path}",
+      dir.delete(recursive: true)));
 }
 
 /**
@@ -257,12 +280,17 @@
   final contents = <String>[];
 
   dir = _getDirectory(dir);
+  log.io("Listing directory ${dir.path}.");
   var lister = dir.list(recursive: recursive);
 
   lister.onDone = (done) {
     // TODO(rnystrom): May need to sort here if it turns out onDir and onFile
     // aren't guaranteed to be called in a certain order. So far, they seem to.
-    if (done) completer.complete(contents);
+    if (done) {
+      log.fine("Listed directory ${dir.path}:\n"
+                "${Strings.join(contents, '\n')}");
+      completer.complete(contents);
+    }
   };
 
   // TODO(nweiz): remove this when issue 4061 is fixed.
@@ -293,7 +321,10 @@
  */
 Future<bool> dirExists(dir) {
   dir = _getDirectory(dir);
-  return dir.exists();
+  return log.ioAsync("Seeing if directory ${dir.path} exists.",
+      dir.exists(),
+      (exists) => "Directory ${dir.path} "
+                  "${exists ? 'exists' : 'does not exist'}.");
 }
 
 /**
@@ -317,29 +348,42 @@
 /// the destination directory.
 Future<Directory> renameDir(from, String to) {
   from = _getDirectory(from);
+  log.io("Renaming directory ${from.path} to $to.");
 
-  if (Platform.operatingSystem != 'windows') return from.rename(to);
+  return _attemptRetryable(() => from.rename(to)).transform((dir) {
+    log.fine("Renamed directory ${from.path} to $to.");
+    return dir;
+  });
+}
 
-  // On Windows, we sometimes get failures where the directory is still in use
-  // when we try to move it. To be a bit more resilient, we wait and retry a
-  // few times.
+/// On Windows, we sometimes get failures where the directory is still in use
+/// when we try to do something with it. This is usually because the OS hasn't
+/// noticed yet that a process using that directory has closed. To be a bit
+/// more resilient, we wait and retry a few times.
+///
+/// Takes a [callback] which returns a future for the operation being attempted.
+/// If that future completes with an error, it will slepp and then [callback]
+/// will be invoked again to retry the operation. It will try a few times before
+/// giving up.
+Future _attemptRetryable(Future callback()) {
+  // Only do lame retry logic on Windows.
+  if (Platform.operatingSystem != 'windows') return callback();
+
   var attempts = 0;
-  attemptRename(_) {
+  makeAttempt(_) {
     attempts++;
-    return from.rename(to).transformException((e) {
+    return callback().transformException((e) {
       if (attempts >= 10) {
-        throw 'Could not move directory "${from.path}" to "$to". Gave up '
-              'after $attempts attempts.';
+        throw 'Could not complete operation. Gave up after $attempts attempts.';
       }
 
       // Wait a bit and try again.
-      return sleep(500).chain(attemptRename);
+      log.fine("Operation failed, retrying (attempt $attempts).");
+      return sleep(500).chain(makeAttempt);
     });
-
-    return from;
   }
 
-  return attemptRename(null);
+  return makeAttempt(null);
 }
 
 /**
@@ -351,6 +395,8 @@
   from = _getPath(from);
   to = _getPath(to);
 
+  log.fine("Create symlink $from -> $to.");
+
   var command = 'ln';
   var args = ['-s', from, to];
 
@@ -382,15 +428,15 @@
   // See if the package has a "lib" directory.
   from = join(from, 'lib');
   return dirExists(from).chain((exists) {
+    log.fine("Creating ${isSelfLink ? "self" : ""}link for package '$name'.");
     if (exists) return createSymlink(from, to);
 
     // It's OK for the self link (i.e. the root package) to not have a lib
     // directory since it may just be a leaf application that only has
     // code in bin or web.
     if (!isSelfLink) {
-      printError(
-          'Warning: Package "$name" does not have a "lib" directory so you '
-          'will not be able to import any libraries from it.');
+      log.warning('Warning: Package "$name" does not have a "lib" directory so '
+                  'you will not be able to import any libraries from it.');
     }
 
     return new Future.immediate(to);
@@ -399,52 +445,25 @@
 
 /// Given [entry] which may be a [String], [File], or [Directory] relative to
 /// the current working directory, returns its full canonicalized path.
-String getFullPath(entry) {
-  var path = _getPath(entry);
-
-  // Don't do anything if it's already absolute.
-  if (isAbsolute(path)) return path;
-
-  // Using Path.join here instead of File().fullPathSync() because the former
-  // does not require an actual file to exist at that path.
-  return new Path.fromNative(currentWorkingDir).join(new Path(path))
-      .toNativePath();
-}
+String getFullPath(entry) => path.absolute(_getPath(entry));
 
 /// Returns whether or not [entry] is an absolute path.
-bool isAbsolute(entry) => _splitAbsolute(entry).first != null;
+bool isAbsolute(entry) => path.isAbsolute(_getPath(entry));
 
-/// Splits [entry] into two components: the absolute path prefix and the
-/// remaining path. Takes into account Windows' quirky absolute paths syntaxes.
-Pair<String, String> _splitAbsolute(entry) {
-  var path = _getPath(entry);
-
-  if (Platform.operatingSystem != 'windows') {
-    return !path.startsWith('/') ? new Pair(null, path)
-        : new Pair('/', path.substring(1));
-  }
-
-  // An absolute path on Windows is either UNC (two leading backslashes),
-  // or a drive letter followed by a colon and a slash.
-  var match = new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])').firstMatch(path);
-  return match == null ? new Pair(null, path)
-      : new Pair(match.group(0), path.substring(match.end));
-}
-
-/// Resolves [path] relative to the location of pub.dart.
-String relativeToPub(String path) {
+/// Resolves [target] relative to the location of pub.dart.
+String relativeToPub(String target) {
   var scriptPath = new File(new Options().script).fullPathSync();
 
   // Walk up until we hit the "util(s)" directory. This lets us figure out where
   // we are if this function is called from pub.dart, or one of the tests,
   // which also live under "utils", or from the SDK where pub is in "util".
-  var utilDir = new Path.fromNative(scriptPath).directoryPath;
-  while (utilDir.filename != 'utils' && utilDir.filename != 'util') {
-    if (utilDir.filename == '') throw 'Could not find path to pub.';
-    utilDir = utilDir.directoryPath;
+  var utilDir = dirname(scriptPath);
+  while (basename(utilDir) != 'utils' && basename(utilDir) != 'util') {
+    if (basename(utilDir) == '') throw 'Could not find path to pub.';
+    utilDir = dirname(utilDir);
   }
 
-  return utilDir.append('pub').append(path).canonicalize().toNativePath();
+  return path.normalize(join(utilDir, 'pub', target));
 }
 
 /// A StringInputStream reading from stdin.
@@ -506,6 +525,9 @@
     : _inner = inner == null ? new http.Client() : inner;
 
   Future<http.StreamedResponse> send(http.BaseRequest request) {
+    log.io("Sending HTTP request $request.");
+    // TODO(rnystrom): Log request body when it's available and plaintext.
+
     // TODO(nweiz): remove this when issue 4061 is fixed.
     var stackTrace;
     try {
@@ -517,6 +539,9 @@
     // TODO(nweiz): Ideally the timeout would extend to reading from the
     // response input stream, but until issue 3657 is fixed that's not feasible.
     return timeout(_inner.send(request).chain((streamedResponse) {
+      log.fine("Got response ${streamedResponse.statusCode} "
+               "${streamedResponse.reasonPhrase}.");
+
       var status = streamedResponse.statusCode;
       // 401 responses should be handled by the OAuth2 client. It's very
       // unlikely that they'll be returned by non-OAuth2 requests.
@@ -557,7 +582,18 @@
     sink.markEndOfStream();
     completer.complete(null);
   };
-  source.onData = () => sink.write(source.read());
+  source.onData = () {
+    // Even if the sink is closed and we aren't going to do anything with more
+    // data, we still need to drain it from source to work around issue 7218.
+    var data = source.read();
+    try {
+      if (!sink.closed) sink.write(data);
+    } on StreamException catch (e, stackTrace) {
+      // Ignore an exception to work around issue 4222.
+      log.io("Writing to an unclosed ListInputStream caused exception $e\n"
+          "$stackTrace");
+    }
+  };
   // TODO(nweiz): propagate this error to the sink. See issue 3657.
   source.onError = (e) { throw e; };
   return completer.future;
@@ -605,6 +641,16 @@
   return completer.future;
 }
 
+/// Wrap an InputStream in a ListInputStream. This eagerly drains the [source]
+/// input stream. This is useful for spawned processes which will not exit until
+/// their output streams have been drained.
+/// TODO(rnystrom): We should use this logic anywhere we spawn a process.
+InputStream wrapInputStream(InputStream source) {
+  var sink = new ListInputStream();
+  pipeInputToInput(source, sink);
+  return sink;
+}
+
 /// Spawns and runs the process located at [executable], passing in [args].
 /// Returns a [Future] that will complete with the results of the process after
 /// it has ended.
@@ -622,9 +668,13 @@
       if (!lines.isEmpty && lines.last == "") lines.removeLast();
       return lines;
     }
-    return new PubProcessResult(toLines(result.stdout),
+
+    var pubResult = new PubProcessResult(toLines(result.stdout),
                                 toLines(result.stderr),
                                 result.exitCode);
+
+    log.processResult(executable, pubResult);
+    return pubResult;
   });
 }
 
@@ -636,7 +686,30 @@
 /// the inherited variables.
 Future<Process> startProcess(String executable, List<String> args,
     {workingDir, Map<String, String> environment}) =>
-  _doProcess(Process.start, executable, args, workingDir, environment);
+  _doProcess(Process.start, executable, args, workingDir, environment)
+    .transform((process) => new _WrappedProcess(process));
+
+/// A wrapper around [Process] that buffers the stdout and stderr to avoid
+/// running into issue 7218.
+class _WrappedProcess implements Process {
+  final Process _process;
+  final InputStream stderr;
+  final InputStream stdout;
+
+  OutputStream get stdin => _process.stdin;
+
+  void set onExit(void callback(int exitCode)) {
+    _process.onExit = callback;
+  }
+
+  _WrappedProcess(Process process)
+    : _process = process,
+      stderr = wrapInputStream(process.stderr),
+      stdout = wrapInputStream(process.stdout);
+
+  bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) =>
+    _process.kill(signal);
+}
 
 /// Calls [fn] with appropriately modified arguments. [fn] should have the same
 /// signature as [Process.start], except that the returned [Future] may have a
@@ -663,34 +736,11 @@
     environment.forEach((key, value) => options.environment[key] = value);
   }
 
+  log.process(executable, args);
+
   return fn(executable, args, options);
 }
 
-/// Closes [response] while ignoring the body of [request]. Returns a Future
-/// that completes once the response is closed.
-///
-/// Due to issue 6984, it's necessary to drain the request body before closing
-/// the response.
-Future closeHttpResponse(HttpRequest request, HttpResponse response) {
-  // TODO(nweiz): remove this when issue 4061 is fixed.
-  var stackTrace;
-  try {
-    throw "";
-  } catch (_, localStackTrace) {
-    stackTrace = localStackTrace;
-  }
-
-  var completer = new Completer();
-  request.inputStream.onError = (e) =>
-      completer.completeException(e, stackTrace);
-  request.inputStream.onData = request.inputStream.read;
-  request.inputStream.onClosed = () {
-    response.outputStream.close();
-    completer.complete(null);
-  };
-  return completer.future;
-}
-
 /**
  * Wraps [input] to provide a timeout. If [input] completes before
  * [milliseconds] have passed, then the return value completes in the same way.
@@ -731,7 +781,10 @@
     tempDir = dir;
     return fn(tempDir.path);
   });
-  future.onComplete((_) => tempDir.delete(recursive: true));
+  future.onComplete((_) {
+    log.fine('Cleaning up temp directory ${tempDir.path}.');
+    deleteDir(tempDir);
+  });
   return future;
 }
 
@@ -804,12 +857,14 @@
 Future<bool> extractTarGz(InputStream stream, destination) {
   destination = _getPath(destination);
 
+  log.fine("Extracting .tar.gz stream to $destination.");
+
   if (Platform.operatingSystem == "windows") {
     return _extractTarGzWindows(stream, destination);
   }
 
   var completer = new Completer<int>();
-  var processFuture = Process.start("tar",
+  var processFuture = startProcess("tar",
       ["--extract", "--gunzip", "--directory", destination]);
   processFuture.then((process) {
     process.onExit = completer.complete;
@@ -822,7 +877,12 @@
     return true;
   });
 
-  return completer.future.transform((exitCode) => exitCode == 0);
+  return completer.future.transform((exitCode) {
+    log.fine("Extracted .tar.gz stream to $destination. Exit code $exitCode.");
+    // TODO(rnystrom): Does anything check this result value? If not, it should
+    // throw on a bad exit code.
+    return exitCode == 0;
+  });
 }
 
 Future<bool> _extractTarGzWindows(InputStream stream, String destination) {
@@ -862,7 +922,7 @@
   }).chain((files) {
     var tarFile;
     for (var file in files) {
-      if (new Path(file).extension == 'tar') {
+      if (path.extension(file) == '.tar') {
         tarFile = file;
         break;
       }
@@ -879,7 +939,7 @@
           '${Strings.join(result.stderr, "\n")}';
     }
 
-    // Clean up the temp directory.
+    log.fine('Clean up 7zip temp directory ${tempDir.path}.');
     // TODO(rnystrom): Should also delete this if anything fails.
     return deleteDir(tempDir);
   }).transform((_) => true);
@@ -890,19 +950,23 @@
 /// considered to be [baseDir], which defaults to the current working directory.
 /// Returns an [InputStream] that will emit the contents of the archive.
 InputStream createTarGz(List contents, {baseDir}) {
+  var buffer = new StringBuffer();
+  buffer.add('Creating .tag.gz stream containing:\n');
+  contents.forEach(buffer.add);
+  log.fine(buffer.toString());
+
   // TODO(nweiz): Propagate errors to the returned stream (including non-zero
   // exit codes). See issue 3657.
   var stream = new ListInputStream();
 
-  if (baseDir == null) baseDir = currentWorkingDir;
+  if (baseDir == null) baseDir = path.current;
   baseDir = getFullPath(baseDir);
   contents = contents.map((entry) {
     entry = getFullPath(entry);
     if (!isBeneath(entry, baseDir)) {
       throw 'Entry $entry is not inside $baseDir.';
     }
-    return new Path.fromNative(entry).relativeTo(new Path.fromNative(baseDir))
-        .toNativePath();
+    return relativeTo(entry, baseDir);
   });
 
   if (Platform.operatingSystem != "windows") {
@@ -913,7 +977,12 @@
     // file and pass them in via --files-from for tar and -i@filename for 7zip.
     startProcess("tar", args).then((process) {
       pipeInputToInput(process.stdout, stream);
-      process.stderr.pipe(stderr, close: false);
+
+      // Drain and discard 7zip's stderr. 7zip writes its normal output to
+      // stderr. We don't want to show that since it's meaningless.
+      // TODO(rnystrom): Should log this and display it if an actual error
+      // occurs.
+      consumeInputStream(process.stderr);
     });
     return stream;
   }
@@ -939,7 +1008,11 @@
       args = ["a", "unused", "-tgzip", "-so", tarFile];
       return startProcess(command, args);
     }).chain((process) {
-      process.stderr.pipe(stderr, close: false);
+      // Drain and discard 7zip's stderr. 7zip writes its normal output to
+      // stderr. We don't want to show that since it's meaningless.
+      // TODO(rnystrom): Should log this and display it if an actual error
+      // occurs.
+      consumeInputStream(process.stderr);
       return pipeInputToInput(process.stdout, stream);
     });
   });
@@ -955,7 +1028,7 @@
   const PubHttpException(this.response);
 
   String toString() => 'HTTP error ${response.statusCode}: '
-    '${response.reasonPhrase}';
+      '${response.reasonPhrase}';
 }
 
 /**
@@ -996,7 +1069,7 @@
 
 /// Gets the path string for [entry], normalizing backslashes to forward slashes
 /// on Windows.
-String sanitizePath(entry) {
+String _sanitizePath(entry) {
   entry = _getPath(entry);
   if (Platform.operatingSystem != 'windows') return entry;
 
@@ -1010,6 +1083,24 @@
          '${split.last.replaceAll('\\', '/')}';
 }
 
+// TODO(nweiz): Add something like this to path.dart.
+/// Splits [entry] into two components: the absolute path prefix and the
+/// remaining path. Takes into account Windows' quirky absolute paths syntaxes.
+Pair<String, String> _splitAbsolute(entry) {
+  var path = _getPath(entry);
+
+  if (Platform.operatingSystem != 'windows') {
+    return !path.startsWith('/') ? new Pair(null, path)
+        : new Pair('/', path.substring(1));
+  }
+
+  // An absolute path on Windows is either UNC (two leading backslashes),
+  // or a drive letter followed by a colon and a slash.
+  var match = new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])').firstMatch(path);
+  return match == null ? new Pair(null, path)
+      : new Pair(match.group(0), path.substring(match.end));
+}
+
 /**
  * Gets a [Directory] for [entry], which can either already be one, or be a
  * [String].
diff --git a/utils/pub/log.dart b/utils/pub/log.dart
new file mode 100644
index 0000000..029f72c
--- /dev/null
+++ b/utils/pub/log.dart
@@ -0,0 +1,228 @@
+// 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.
+
+/// Message logging.
+library log;
+
+import 'dart:io';
+import 'io.dart';
+
+typedef LogFn(Entry entry);
+final Map<Level, LogFn> _loggers = new Map<Level, LogFn>();
+
+/// The list of recorded log messages. Will only be recorded if
+/// [recordTranscript()] is called.
+List<Entry> _transcript;
+
+/// An enum type for defining the different logging levels. By default, [ERROR]
+/// and [WARNING] messages are printed to sterr. [MESSAGE] messages are printed
+/// to stdout, and others are ignored.
+class Level {
+  /// An error occurred and an operation could not be completed. Usually shown
+  /// to the user on stderr.
+  static const ERROR = const Level._("ERR ");
+
+  /// Something unexpected happened, but the program was able to continue,
+  /// though possibly in a degraded fashion.
+  static const WARNING = const Level._("WARN");
+
+  /// A message intended specifically to be shown to the user.
+  static const MESSAGE = const Level._("MSG ");
+
+  /// Some interaction with the external world occurred, such as a network
+  /// operation, process spawning, or file IO.
+  static const IO = const Level._("IO  ");
+
+  /// Fine-grained and verbose additional information. Can be used to provide
+  /// program state context for other logs (such as what pub was doing when an
+  /// IO operation occurred) or just more detail for an operation.
+  static const FINE = const Level._("FINE");
+
+  const Level._(this.name);
+  final String name;
+
+  String toString() => name;
+  int get hashCode => name.hashCode;
+}
+
+/// A single log entry.
+class Entry {
+  final Level level;
+  final List<String> lines;
+
+  Entry(this.level, this.lines);
+}
+
+/// Logs [message] at [Level.ERROR].
+void error(message) => write(Level.ERROR, message);
+
+/// Logs [message] at [Level.WARNING].
+void warning(message) => write(Level.WARNING, message);
+
+/// Logs [message] at [Level.MESSAGE].
+void message(message) => write(Level.MESSAGE, message);
+
+/// Logs [message] at [Level.IO].
+void io(message) => write(Level.IO, message);
+
+/// Logs [message] at [Level.FINE].
+void fine(message) => write(Level.FINE, message);
+
+/// Logs [message] at [level].
+void write(Level level, message) {
+  if (_loggers.isEmpty) showNormal();
+
+  var lines = message.toString().split(NEWLINE_PATTERN);
+  var entry = new Entry(level, lines);
+
+  var logFn = _loggers[level];
+  if (logFn != null) logFn(entry);
+
+  if (_transcript != null) _transcript.add(entry);
+}
+
+/// Logs an asynchronous IO operation. Logs [startMessage] before the operation
+/// starts, then when [operation] completes, invokes [endMessage] with the
+/// completion value and logs the result of that. Returns a future that
+/// completes after the logging is done.
+///
+/// If [endMessage] is omitted, then logs "Begin [startMessage]" before the
+/// operation and "End [startMessage]" after it.
+Future ioAsync(String startMessage, Future operation,
+               [String endMessage(value)]) {
+  if (endMessage == null) {
+    io("Begin $startMessage.");
+  } else {
+    io(startMessage);
+  }
+
+  return operation.transform((result) {
+    if (endMessage == null) {
+      io("End $startMessage.");
+    } else {
+      io(endMessage(result));
+    }
+    return result;
+  });
+}
+
+/// Logs the spawning of an [executable] process with [arguments] at [IO]
+/// level.
+void process(String executable, List<String> arguments) {
+  io("Spawning $executable ${Strings.join(arguments, ' ')}");
+}
+
+/// Logs the results of running [executable].
+void processResult(String executable, PubProcessResult result) {
+  // Log it all as one message so that it shows up as a single unit in the logs.
+  var buffer = new StringBuffer();
+  buffer.add("Finished $executable. Exit code ${result.exitCode}.");
+
+  dumpOutput(String name, List<String> output) {
+    if (output.length == 0) {
+      buffer.add("Nothing output on $name.");
+    } else {
+      buffer.add("$name:");
+      var numLines = 0;
+      for (var line in output) {
+        if (++numLines > 1000) {
+          buffer.add('[${output.length - 1000}] more lines of output '
+                     'truncated...]');
+          break;
+        }
+
+        buffer.add(line);
+      }
+    }
+  }
+
+  dumpOutput("stdout", result.stdout);
+  dumpOutput("stderr", result.stderr);
+
+  io(buffer.toString());
+}
+
+/// Enables recording of log entries.
+void recordTranscript() {
+  _transcript = <Entry>[];
+}
+
+/// If [recordTranscript()] was called, then prints the previously recorded log
+/// transcript to stderr.
+void dumpTranscript() {
+  if (_transcript == null) return;
+
+  stderr.writeString('---- Log transcript ----\n');
+  for (var entry in _transcript) {
+    _logToStderrWithLabel(entry);
+  }
+  stderr.writeString('---- End log transcript ----\n');
+}
+
+/// Sets the verbosity to "normal", which shows errors, warnings, and messages.
+void showNormal() {
+  _loggers[Level.ERROR]   = _logToStderr;
+  _loggers[Level.WARNING] = _logToStderr;
+  _loggers[Level.MESSAGE] = _logToStdout;
+  _loggers[Level.IO]      = null;
+  _loggers[Level.FINE]    = null;
+}
+
+/// Sets the verbosity to "io", which shows errors, warnings, messages, and IO
+/// event logs.
+void showIO() {
+  _loggers[Level.ERROR]   = _logToStderrWithLabel;
+  _loggers[Level.WARNING] = _logToStderrWithLabel;
+  _loggers[Level.MESSAGE] = _logToStdoutWithLabel;
+  _loggers[Level.IO]      = _logToStderrWithLabel;
+  _loggers[Level.FINE]    = null;
+}
+
+/// Sets the verbosity to "all", which logs ALL the things.
+void showAll() {
+  _loggers[Level.ERROR]   = _logToStderrWithLabel;
+  _loggers[Level.WARNING] = _logToStderrWithLabel;
+  _loggers[Level.MESSAGE] = _logToStdoutWithLabel;
+  _loggers[Level.IO]      = _logToStderrWithLabel;
+  _loggers[Level.FINE]    = _logToStderrWithLabel;
+}
+
+/// Log function that prints the message to stdout.
+void _logToStdout(Entry entry) {
+  _logToStream(stdout, entry, showLabel: false);
+}
+
+/// Log function that prints the message to stdout with the level name.
+void _logToStdoutWithLabel(Entry entry) {
+  _logToStream(stdout, entry, showLabel: true);
+}
+
+/// Log function that prints the message to stderr.
+void _logToStderr(Entry entry) {
+  _logToStream(stderr, entry, showLabel: false);
+}
+
+/// Log function that prints the message to stderr with the level name.
+void _logToStderrWithLabel(Entry entry) {
+  _logToStream(stderr, entry, showLabel: true);
+}
+
+void _logToStream(OutputStream stream, Entry entry, {bool showLabel}) {
+  bool firstLine = true;
+  for (var line in entry.lines) {
+    if (showLabel) {
+      if (firstLine) {
+        stream.writeString(entry.level.name);
+        stream.writeString(': ');
+      } else {
+        stream.writeString('    | ');
+      }
+    }
+
+    stream.writeString(line);
+    stream.writeString('\n');
+
+    firstLine = false;
+  }
+}
diff --git a/utils/pub/oauth2.dart b/utils/pub/oauth2.dart
index c7a87fd..78cd4c2 100644
--- a/utils/pub/oauth2.dart
+++ b/utils/pub/oauth2.dart
@@ -10,6 +10,7 @@
 // TODO(nweiz): Make this a "package:" URL, or something nicer than this.
 import '../../pkg/oauth2/lib/oauth2.dart';
 import 'io.dart';
+import 'log.dart' as log;
 import 'system_cache.dart';
 import 'utils.dart';
 
@@ -100,14 +101,24 @@
 /// filesystem if possible. If the credentials can't be loaded for any reason,
 /// the returned [Future] will complete to null.
 Future<Credentials> _loadCredentials(SystemCache cache) {
-  if (_credentials != null) return new Future.immediate(_credentials);
-  return fileExists(_credentialsFile(cache)).chain((credentialsExist) {
-    if (!credentialsExist) return new Future.immediate(null);
+  log.fine('Loading OAuth2 credentials.');
+
+  if (_credentials != null) {
+    log.fine('Using already-loaded credentials.');
+    return new Future.immediate(_credentials);
+  }
+
+  var path = _credentialsFile(cache);
+  return fileExists(path).chain((credentialsExist) {
+    if (!credentialsExist) {
+      log.fine('No credentials found at $path.');
+      return new Future.immediate(null);
+    }
 
     return readTextFile(_credentialsFile(cache)).transform((credentialsJson) {
       var credentials = new Credentials.fromJson(credentialsJson);
       if (credentials.isExpired && !credentials.canRefresh) {
-        printError("Pub's authorization to upload packages has expired and "
+        log.error("Pub's authorization to upload packages has expired and "
             "can't be automatically refreshed.");
         return null; // null means re-authorize
       }
@@ -115,8 +126,7 @@
       return credentials;
     });
   }).transformException((e) {
-    printError('Warning: could not load the saved OAuth2 credentials:'
-        '  $e\n'
+    log.error('Warning: could not load the saved OAuth2 credentials: $e\n'
         'Obtaining new credentials...');
     return null; // null means re-authorize
   });
@@ -125,10 +135,11 @@
 /// Save the user's OAuth2 credentials to the in-memory cache and the
 /// filesystem.
 Future _saveCredentials(SystemCache cache, Credentials credentials) {
+  log.fine('Saving OAuth2 credentials.');
   _credentials = credentials;
-  var credentialsFile = _credentialsFile(cache);
-  return ensureDir(dirname(credentialsFile)).chain((_) =>
-      writeTextFile(credentialsFile, credentials.toJson()));
+  var path = _credentialsFile(cache);
+  return ensureDir(dirname(path)).chain((_) =>
+      writeTextFile(path, credentials.toJson()));
 }
 
 /// The path to the file in which the user's OAuth2 credentials are stored.
@@ -161,18 +172,16 @@
   server.addRequestHandler((request) => request.path == "/",
       (request, response) {
     chainToCompleter(new Future.immediate(null).chain((_) {
-      print('Authorization received, processing...');
+      log.message('Authorization received, processing...');
       var queryString = request.queryString;
       if (queryString == null) queryString = '';
       response.statusCode = 302;
       response.headers.set('location', 'http://pub.dartlang.org/authorized');
-      return Futures.wait([
-        closeHttpResponse(request, response),
-        grant.handleAuthorizationResponse(queryToMap(queryString))
-      ]);
-    }).transform((results) {
+      response.outputStream.close();
+      return grant.handleAuthorizationResponse(queryToMap(queryString));
+    }).transform((client) {
       server.close();
-      return results[1];
+      return client;
     }), completer);
   });
   server.listen('127.0.0.1', 0);
@@ -180,13 +189,14 @@
   var authUrl = grant.getAuthorizationUrl(
       new Uri.fromString('http://localhost:${server.port}'), scopes: _scopes);
 
-  print('Pub needs your authorization to upload packages on your behalf.\n'
-        'In a web browser, go to $authUrl\n'
-        'Then click "Allow access".\n\n'
-        'Waiting for your authorization...');
+  log.message(
+      'Pub needs your authorization to upload packages on your behalf.\n'
+      'In a web browser, go to $authUrl\n'
+      'Then click "Allow access".\n\n'
+      'Waiting for your authorization...');
 
   return completer.future.transform((client) {
-    print('Successfully authorized.\n');
+    log.message('Successfully authorized.\n');
     return client;
   });
 }
\ No newline at end of file
diff --git a/utils/pub/path.dart b/utils/pub/path.dart
new file mode 100644
index 0000000..d803fd1
--- /dev/null
+++ b/utils/pub/path.dart
@@ -0,0 +1,535 @@
+// 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.
+
+/// A comprehensive, cross-platform path manipulation library.
+library path;
+
+import 'dart:io' as io;
+
+/// An internal builder for the current OS so we can provide a straight
+/// functional interface and not require users to create one.
+final _builder = new Builder();
+
+/// Gets the path to the current working directory.
+String get current => new io.Directory.current().path;
+
+/// Gets the path separator for the current platform. On Mac and Linux, this
+/// is `/`. On Windows, it's `\`.
+String get separator => _builder.separator;
+
+/// Converts [path] to an absolute path by resolving it relative to the current
+/// working directory. If [path] is already an absolute path, just returns it.
+///
+///     path.absolute('foo/bar.txt'); // -> /your/current/dir/foo/bar.txt
+String absolute(String path) => join(current, path);
+
+/// Gets the part of [path] after the last separator.
+///
+///     path.basename('path/to/foo.dart'); // -> 'foo.dart'
+///     path.basename('path/to');          // -> 'to'
+String basename(String path) => _builder.basename(path);
+
+/// Gets the part of [path] after the last separator, and without any trailing
+/// file extension.
+///
+///     path.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo'
+String basenameWithoutExtension(String path) =>
+    _builder.basenameWithoutExtension(path);
+
+/// Gets the file extension of [path]: the portion of [basename] from the last
+/// `.` to the end (including the `.` itself).
+///
+///     path.extension('path/to/foo.dart');    // -> '.dart'
+///     path.extension('path/to/foo');         // -> ''
+///     path.extension('path.to/foo');         // -> ''
+///     path.extension('path/to/foo.dart.js'); // -> '.js'
+///
+/// If the file name starts with a `.`, then that is not considered the
+/// extension:
+///
+///     path.extension('~/.bashrc');    // -> ''
+///     path.extension('~/.notes.txt'); // -> '.txt'
+String extension(String path) => _builder.extension(path);
+
+/// Returns `true` if [path] is an absolute path and `false` if it is a
+/// relative path. On POSIX systems, absolute paths start with a `/` (forward
+/// slash). On Windows, an absolute path starts with `\\`, or a drive letter
+/// followed by `:/` or `:\`.
+bool isAbsolute(String path) => _builder.isAbsolute(path);
+
+/// Returns `true` if [path] is a relative path and `false` if it is absolute.
+/// On POSIX systems, absolute paths start with a `/` (forward slash). On
+/// Windows, an absolute path starts with `\\`, or a drive letter followed by
+/// `:/` or `:\`.
+bool isRelative(String path) => _builder.isRelative(path);
+
+/// Joins the given path parts into a single path using the current platform's
+/// [separator]. Example:
+///
+///     path.join('path', 'to', 'foo'); // -> 'path/to/foo'
+///
+/// If any part ends in a path separator, then a redundant separator will not
+/// be added:
+///
+///     path.join('path/', 'to', 'foo'); // -> 'path/to/foo
+///
+/// If a part is an absolute path, then anything before that will be ignored:
+///
+///     path.join('path', '/to', 'foo'); // -> '/to/foo'
+String join(String part1, [String part2, String part3, String part4,
+            String part5, String part6, String part7, String part8]) {
+  if (!?part2) return _builder.join(part1);
+  if (!?part3) return _builder.join(part1, part2);
+  if (!?part4) return _builder.join(part1, part2, part3);
+  if (!?part5) return _builder.join(part1, part2, part3, part4);
+  if (!?part6) return _builder.join(part1, part2, part3, part4, part5);
+  if (!?part7) return _builder.join(part1, part2, part3, part4, part5, part6);
+  if (!?part8) return _builder.join(part1, part2, part3, part4, part5, part6,
+                                    part7);
+  return _builder.join(part1, part2, part3, part4, part5, part6, part7, part8);
+}
+
+/// Normalizes [path], simplifying it by handling `..`, and `.`, and
+/// removing redundant path separators whenever possible.
+///
+///     path.normalize('path/./to/..//file.text'); // -> 'path/file.txt'
+String normalize(String path) => _builder.normalize(path);
+
+/// Attempts to convert [path] to an equivalent relative path from the current
+/// directory.
+///
+///     // Given current directory is /root/path:
+///     path.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
+///     path.relative('/root/other.dart'); // -> '../other.dart'
+///
+/// Since there is no relative path from one drive letter to another on Windows,
+/// this will return an absolute path in that case.
+///
+///     // Given current directory is C:\home:
+///     path.relative(r'D:\other'); // -> 'D:\other'
+String relative(String path) => _builder.relative(path);
+
+/// Removes a trailing extension from the last part of [path].
+///
+///     withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'
+String withoutExtension(String path) => _builder.withoutExtension(path);
+
+/// An instantiable class for manipulating paths. Unlike the top-level
+/// functions, this lets you explicitly select what platform the paths will use.
+class Builder {
+  /// Creates a new path builder for the given style and root directory.
+  ///
+  /// If [style] is omitted, it uses the host operating system's path style. If
+  /// [root] is omitted, it defaults to the current working directory. If [root]
+  /// is relative, it is considered relative to the current working directory.
+  factory Builder({Style style, String root}) {
+    if (style == null) {
+      if (io.Platform.operatingSystem == 'windows') {
+        style = Style.windows;
+      } else {
+        style = Style.posix;
+      }
+    }
+
+    if (root == null) root = current;
+
+    return new Builder._(style, root);
+  }
+
+  Builder._(this.style, this.root);
+
+  /// The style of path that this builder works with.
+  final Style style;
+
+  /// The root directory that relative paths will be relative to.
+  final String root;
+
+  /// Gets the path separator for the builder's [style]. On Mac and Linux,
+  /// this is `/`. On Windows, it's `\`.
+  String get separator => style.separator;
+
+  /// Gets the part of [path] after the last separator on the builder's
+  /// platform.
+  ///
+  ///     builder.basename('path/to/foo.dart'); // -> 'foo.dart'
+  ///     builder.basename('path/to');          // -> 'to'
+  String basename(String path) => _parse(path).basename;
+
+  /// Gets the part of [path] after the last separator on the builder's
+  /// platform, and without any trailing file extension.
+  ///
+  ///     builder.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo'
+  String basenameWithoutExtension(String path) =>
+      _parse(path).basenameWithoutExtension;
+
+  /// Gets the file extension of [path]: the portion of [basename] from the last
+  /// `.` to the end (including the `.` itself).
+  ///
+  ///     builder.extension('path/to/foo.dart'); // -> '.dart'
+  ///     builder.extension('path/to/foo'); // -> ''
+  ///     builder.extension('path.to/foo'); // -> ''
+  ///     builder.extension('path/to/foo.dart.js'); // -> '.js'
+  ///
+  /// If the file name starts with a `.`, then it is not considered an
+  /// extension:
+  ///
+  ///     builder.extension('~/.bashrc');    // -> ''
+  ///     builder.extension('~/.notes.txt'); // -> '.txt'
+  String extension(String path) => _parse(path).extension;
+
+  /// Returns `true` if [path] is an absolute path and `false` if it is a
+  /// relative path. On POSIX systems, absolute paths start with a `/` (forward
+  /// slash). On Windows, an absolute path starts with `\\`, or a drive letter
+  /// followed by `:/` or `:\`.
+  bool isAbsolute(String path) => _parse(path).isAbsolute;
+
+  /// Returns `true` if [path] is a relative path and `false` if it is absolute.
+  /// On POSIX systems, absolute paths start with a `/` (forward slash). On
+  /// Windows, an absolute path starts with `\\`, or a drive letter followed by
+  /// `:/` or `:\`.
+  bool isRelative(String path) => !isAbsolute(path);
+
+  /// Joins the given path parts into a single path. Example:
+  ///
+  ///     builder.join('path', 'to', 'foo'); // -> 'path/to/foo'
+  ///
+  /// If any part ends in a path separator, then a redundant separator will not
+  /// be added:
+  ///
+  ///     builder.join('path/', 'to', 'foo'); // -> 'path/to/foo
+  ///
+  /// If a part is an absolute path, then anything before that will be ignored:
+  ///
+  ///     builder.join('path', '/to', 'foo'); // -> '/to/foo'
+  ///
+  String join(String part1, [String part2, String part3, String part4,
+              String part5, String part6, String part7, String part8]) {
+    var buffer = new StringBuffer();
+    var needsSeparator = false;
+
+    addPart(condition, part) {
+      if (!condition) return;
+
+      if (this.isAbsolute(part)) {
+        // An absolute path discards everything before it.
+        buffer.clear();
+        buffer.add(part);
+      } else {
+        if (part.length > 0 && style.separatorPattern.hasMatch(part[0])) {
+          // The part starts with a separator, so we don't need to add one.
+        } else if (needsSeparator) {
+          buffer.add(separator);
+        }
+
+        buffer.add(part);
+      }
+
+      // Unless this part ends with a separator, we'll need to add one before
+      // the next part.
+      needsSeparator = part.length > 0 &&
+          !style.separatorPattern.hasMatch(part[part.length - 1]);
+    }
+
+    addPart(true, part1);
+    addPart(?part2, part2);
+    addPart(?part3, part3);
+    addPart(?part4, part4);
+    addPart(?part5, part5);
+    addPart(?part6, part6);
+    addPart(?part7, part7);
+    addPart(?part8, part8);
+
+    return buffer.toString();
+  }
+
+  /// Normalizes [path], simplifying it by handling `..`, and `.`, and
+  /// removing redundant path separators whenever possible.
+  ///
+  ///     builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt'
+  String normalize(String path) {
+    if (path == '') return path;
+
+    var parsed = _parse(path);
+    parsed.normalize();
+    return parsed.toString();
+  }
+
+  /// Creates a new path by appending the given path parts to the [root].
+  /// Equivalent to [join()] with [root] as the first argument. Example:
+  ///
+  ///     var builder = new Builder(root: 'root');
+  ///     builder.resolve('path', 'to', 'foo'); // -> 'root/path/to/foo'
+  String resolve(String part1, [String part2, String part3, String part4,
+              String part5, String part6, String part7]) {
+    if (!?part2) return join(root, part1);
+    if (!?part3) return join(root, part1, part2);
+    if (!?part4) return join(root, part1, part2, part3);
+    if (!?part5) return join(root, part1, part2, part3, part4);
+    if (!?part6) return join(root, part1, part2, part3, part4, part5);
+    if (!?part7) return join(root, part1, part2, part3, part4, part5, part6);
+    return join(root, part1, part2, part3, part4, part5, part6, part7);
+  }
+
+  /// Attempts to convert [path] to an equivalent relative path relative to
+  /// [root].
+  ///
+  ///     var builder = new Builder(root: '/root/path');
+  ///     builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
+  ///     builder.relative('/root/other.dart'); // -> '../other.dart'
+  ///
+  /// Since there is no relative path from one drive letter to another on
+  /// Windows, this will return an absolute path in that case.
+  ///
+  ///     var builder = new Builder(root: r'C:\home');
+  ///     builder.relative(r'D:\other'); // -> 'D:\other'
+  String relative(String path) {
+    if (path == '') return '.';
+
+    // If the base path is relative, resolve it relative to the current
+    // directory.
+    var base = root;
+    if (this.isRelative(base)) base = absolute(base);
+
+    // If the given path is relative, resolve it relative to the base.
+    if (this.isRelative(path)) return this.normalize(path);
+
+    var baseParsed = _parse(base)..normalize();
+    var pathParsed = _parse(path)..normalize();
+
+    // If the root prefixes don't match (for example, different drive letters
+    // on Windows), then there is no relative path, so just return the absolute
+    // one.
+    // TODO(rnystrom): Drive letters are case-insentive on Windows. Should
+    // handle "C:\" and "c:\" being the same root.
+    if (baseParsed.root != pathParsed.root) return pathParsed.toString();
+
+    // Strip off their common prefix.
+    while (baseParsed.parts.length > 0 && pathParsed.parts.length > 0 &&
+           baseParsed.parts[0] == pathParsed.parts[0]) {
+      baseParsed.parts.removeAt(0);
+      baseParsed.separators.removeAt(0);
+      pathParsed.parts.removeAt(0);
+      pathParsed.separators.removeAt(0);
+    }
+
+    // If there are any directories left in the root path, we need to walk up
+    // out of them.
+    pathParsed.parts.insertRange(0, baseParsed.parts.length, '..');
+    pathParsed.separators.insertRange(0, baseParsed.parts.length,
+        style.separator);
+
+    // Corner case: the paths completely collapsed.
+    if (pathParsed.parts.length == 0) return '.';
+
+    // Make it relative.
+    pathParsed.root = '';
+    pathParsed.removeTrailingSeparator();
+
+    return pathParsed.toString();
+  }
+
+  /// Removes a trailing extension from the last part of [path].
+  ///
+  ///     builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'
+  String withoutExtension(String path) {
+    var parsed = _parse(path);
+    if (parsed.hasTrailingSeparator) return parsed.toString();
+
+    if (!parsed.parts.isEmpty) {
+      parsed.parts[parsed.parts.length - 1] = parsed.basenameWithoutExtension;
+    }
+
+    return parsed.toString();
+  }
+
+  _ParsedPath _parse(String path) {
+    var before = path;
+
+    // Remove the root prefix, if any.
+    var root = style.getRoot(path);
+    if (root != null) path = path.substring(root.length);
+
+    // Split the parts on path separators.
+    var parts = [];
+    var separators = [];
+    var start = 0;
+    for (var match in style.separatorPattern.allMatches(path)) {
+      parts.add(path.substring(start, match.start));
+      separators.add(match[0]);
+      start = match.end;
+    }
+
+    // Add the final part, if any.
+    if (start < path.length) {
+      parts.add(path.substring(start));
+      separators.add('');
+    }
+
+    return new _ParsedPath(style, root, parts, separators);
+  }
+}
+
+/// An enum type describing a "flavor" of path.
+class Style {
+  /// POSIX-style paths use "/" (forward slash) as separators. Absolute paths
+  /// start with "/". Used by UNIX, Linux, Mac OS X, and others.
+  static final posix = new Style._('posix', '/', '/', '/');
+
+  /// Windows paths use "\" (backslash) as separators. Absolute paths start with
+  /// a drive letter followed by a colon (example, "C:") or two backslashes
+  /// ("\\") for UNC paths.
+  // TODO(rnystrom): The UNC root prefix should include the drive name too, not
+  // just the "\\".
+  static final windows = new Style._('windows', '\\', r'[/\\]',
+      r'\\\\|[a-zA-Z]:[/\\]');
+
+  Style._(this.name, this.separator, String separatorPattern,
+      String rootPattern)
+    : separatorPattern = new RegExp(separatorPattern),
+      _rootPattern = new RegExp('^$rootPattern');
+
+  /// The name of this path style. Will be "posix" or "windows".
+  final String name;
+
+  /// The path separator for this style. On POSIX, this is `/`. On Windows,
+  /// it's `\`.
+  final String separator;
+
+  /// The [Pattern] that can be used to match a separator for a path in this
+  /// style. Windows allows both "/" and "\" as path separators even though
+  /// "\" is the canonical one.
+  final Pattern separatorPattern;
+
+  /// The [Pattern] that can be used to match the root prefix of an absolute
+  /// path in this style.
+  final Pattern _rootPattern;
+
+  /// Gets the root prefix of [path] if path is absolute. If [path] is relative,
+  /// returns `null`.
+  String getRoot(String path) {
+    var match = _rootPattern.firstMatch(path);
+    if (match == null) return null;
+    return match[0];
+  }
+
+  String toString() => name;
+}
+
+// TODO(rnystrom): Make this public?
+class _ParsedPath {
+  /// The [Style] that was used to parse this path.
+  Style style;
+
+  /// The absolute root portion of the path, or `null` if the path is relative.
+  /// On POSIX systems, this will be `null` or "/". On Windows, it can be
+  /// `null`, "//" for a UNC path, or something like "C:\" for paths with drive
+  /// letters.
+  String root;
+
+  /// The path-separated parts of the path. All but the last will be
+  /// directories.
+  List<String> parts;
+
+  /// The path separators following each part. The last one will be an empty
+  /// string unless the path ends with a trailing separator.
+  List<String> separators;
+
+  /// The file extension of the last part, or "" if it doesn't have one.
+  String get extension => _splitExtension()[1];
+
+  /// `true` if the path ends with a trailing separator.
+  bool get hasTrailingSeparator {
+    if (separators.length == 0) return false;
+    return separators[separators.length - 1] != '';
+  }
+
+  /// `true` if this is an absolute path.
+  bool get isAbsolute => root != null;
+
+  _ParsedPath(this.style, this.root, this.parts, this.separators);
+
+  String get basename {
+    if (parts.length == 0) return extension;
+    if (hasTrailingSeparator) return '';
+    return parts.last;
+  }
+
+  String get basenameWithoutExtension => _splitExtension()[0];
+
+  void removeTrailingSeparator() {
+    if (separators.length > 0) {
+      separators[separators.length - 1] = '';
+    }
+  }
+
+  void normalize() {
+    // Handle '.', '..', and empty parts.
+    var leadingDoubles = 0;
+    var newParts = [];
+    for (var part in parts) {
+      if (part == '.' || part == '') {
+        // Do nothing. Ignore it.
+      } else if (part == '..') {
+        // Pop the last part off.
+        if (newParts.length > 0) {
+          newParts.removeLast();
+        } else {
+          // Backed out past the beginning, so preserve the "..".
+          leadingDoubles++;
+        }
+      } else {
+        newParts.add(part);
+      }
+    }
+
+    // A relative path can back out from the start directory.
+    if (!isAbsolute) {
+      newParts.insertRange(0, leadingDoubles, '..');
+    }
+
+    // If we collapsed down to nothing, do ".".
+    if (newParts.length == 0 && !isAbsolute) {
+      newParts.add('.');
+    }
+
+    // Canonicalize separators.
+    var newSeparators = [];
+    newSeparators.insertRange(0, newParts.length, style.separator);
+
+    parts = newParts;
+    separators = newSeparators;
+
+    removeTrailingSeparator();
+  }
+
+  String toString() {
+    var builder = new StringBuffer();
+    if (root != null) builder.add(root);
+    for (var i = 0; i < parts.length; i++) {
+      builder.add(parts[i]);
+      builder.add(separators[i]);
+    }
+
+    return builder.toString();
+  }
+
+  /// Splits the last part of the path into a two-element list. The first is
+  /// the name of the file without any extension. The second is the extension
+  /// or "" if it has none.
+  List<String> _splitExtension() {
+    if (parts.isEmpty) return ['', ''];
+    if (hasTrailingSeparator) return ['', ''];
+
+    var file = parts.last;
+    if (file == '..') return ['..', ''];
+
+    var lastDot = file.lastIndexOf('.');
+
+    // If there is no dot, or it's the first character, like '.bashrc', it
+    // doesn't count.
+    if (lastDot <= 0) return [file, ''];
+
+    return [file.substring(0, lastDot), file.substring(lastDot)];
+  }
+}
diff --git a/utils/pub/pub.dart b/utils/pub/pub.dart
index 1daf20d..835a09d 100644
--- a/utils/pub/pub.dart
+++ b/utils/pub/pub.dart
@@ -18,7 +18,9 @@
 import 'command_version.dart';
 import 'entrypoint.dart';
 import 'exit_codes.dart' as exit_codes;
+import 'log.dart' as log;
 import 'package.dart';
+import 'path.dart' as path;
 import 'pubspec.dart';
 import 'source.dart';
 import 'source_registry.dart';
@@ -54,10 +56,21 @@
 ArgParser get pubArgParser {
   var parser = new ArgParser();
   parser.addFlag('help', abbr: 'h', negatable: false,
-    help: 'Prints this usage information');
+      help: 'Print this usage information.');
   parser.addFlag('version', negatable: false,
-    help: 'Prints the version of Pub');
-  parser.addFlag('trace', help: 'Prints a stack trace when an error occurs');
+      help: 'Print pub version.');
+  parser.addFlag('trace',
+       help: 'Print debugging information when an error occurs.');
+  parser.addOption('verbosity',
+      help: 'Control output verbosity.',
+      allowed: ['normal', 'io', 'all'],
+      allowedHelp: {
+        'normal': 'Errors, warnings, and user messages are shown.',
+        'io':     'IO operations are also shown.',
+        'all':    'All output including internal tracing messages are shown.'
+      });
+  parser.addFlag('verbose', abbr: 'v', negatable: false,
+      help: 'Shortcut for "--verbosity=all"');
   return parser;
 }
 
@@ -66,8 +79,8 @@
   try {
     globalOptions = pubArgParser.parse(new Options().arguments);
   } on FormatException catch (e) {
-    printError(e.message);
-    printError('Run "pub help" to see available options.');
+    log.error(e.message);
+    log.error('Run "pub help" to see available options.');
     exit(exit_codes.USAGE);
   }
 
@@ -81,6 +94,24 @@
     return;
   }
 
+  if (globalOptions['trace']) {
+    log.recordTranscript();
+  }
+
+  switch (globalOptions['verbosity']) {
+    case 'normal': log.showNormal(); break;
+    case 'io': log.showIO(); break;
+    case 'all': log.showAll(); break;
+    default:
+      // No specific verbosity given, so check for the shortcut.
+      if (globalOptions['verbose']) {
+        log.showAll();
+      } else {
+        log.showNormal();
+      }
+      break;
+  }
+
   // TODO(nweiz): Have a fallback for this this out automatically once 1145 is
   // fixed.
   var sdkDir = Platform.environment['DART_SDK'];
@@ -99,8 +130,8 @@
   // Select the command.
   var command = pubCommands[globalOptions.rest[0]];
   if (command == null) {
-    printError('Could not find a command named "${globalOptions.rest[0]}".');
-    printError('Run "pub help" to see available commands.');
+    log.error('Could not find a command named "${globalOptions.rest[0]}".');
+    log.error('Run "pub help" to see available commands.');
     exit(exit_codes.USAGE);
     return;
   }
@@ -112,16 +143,16 @@
 
 /** Displays usage information for the app. */
 void printUsage([String description = 'Pub is a package manager for Dart.']) {
-  print(description);
-  print('');
-  print('Usage: pub command [arguments]');
-  print('');
-  print('Global options:');
-  print(pubArgParser.getUsage());
-  print('');
+  // Build up a buffer so it shows up as a single log entry.
+  var buffer = new StringBuffer();
+  buffer.add(description);
+  buffer.add('\n\n');
+  buffer.add('Usage: pub command [arguments]\n\n');
+  buffer.add('Global options:\n');
+  buffer.add('${pubArgParser.getUsage()}\n\n');
 
   // Show the commands sorted.
-  print('Available commands:');
+  buffer.add('Available commands:\n');
 
   // TODO(rnystrom): A sorted map would be nice.
   int length = 0;
@@ -136,15 +167,17 @@
   names.sort((a, b) => a.compareTo(b));
 
   for (var name in names) {
-    print('  ${padRight(name, length)}   ${pubCommands[name].description}');
+    buffer.add('  ${padRight(name, length)}   '
+        '${pubCommands[name].description}\n');
   }
 
-  print('');
-  print('Use "pub help [command]" for more information about a command.');
+  buffer.add('\n');
+  buffer.add('Use "pub help [command]" for more information about a command.');
+  log.message(buffer.toString());
 }
 
 void printVersion() {
-  print('Pub $pubVersion');
+  log.message('Pub $pubVersion');
 }
 
 abstract class PubCommand {
@@ -187,8 +220,8 @@
     try {
      commandOptions = commandParser.parse(commandArgs);
     } on FormatException catch (e) {
-      printError(e.message);
-      printError('Use "pub help" for more information.');
+      log.error(e.message);
+      log.error('Use "pub help" for more information.');
       exit(exit_codes.USAGE);
     }
 
@@ -203,9 +236,10 @@
         message = message.substring("Exception: ".length);
       }
 
-      printError(message);
+      log.error(message);
       if (globalOptions['trace'] && trace != null) {
-        printError(trace);
+        log.error(trace);
+        log.dumpTranscript();
       }
 
       exit(_chooseExitCode(error));
@@ -216,7 +250,7 @@
       // TODO(rnystrom): Will eventually need better logic to walk up
       // subdirectories until we hit one that looks package-like. For now, just
       // assume the cwd is it.
-      future = Entrypoint.load(currentWorkingDir, cache);
+      future = Entrypoint.load(path.current, cache);
     }
 
     future = future.chain((entrypoint) {
@@ -237,10 +271,10 @@
     future.handleException((e) {
       if (e is PubspecNotFoundException && e.name == null) {
         e = 'Could not find a file named "pubspec.yaml" in the directory '
-          '$currentWorkingDir.';
+          '${path.current}.';
       } else if (e is PubspecHasNoNameException && e.name == null) {
         e = 'pubspec.yaml is missing the required "name" field (e.g. "name: '
-          '${basename(currentWorkingDir)}").';
+          '${basename(path.current)}").';
       }
 
       handleError(e, future.stackTrace);
@@ -261,15 +295,17 @@
   /** Displays usage information for this command. */
   void printUsage([String description]) {
     if (description == null) description = this.description;
-    print(description);
-    print('');
-    print('Usage: $usage');
+
+    var buffer = new StringBuffer();
+    buffer.add('$description\n\nUsage: $usage');
 
     var commandUsage = commandParser.getUsage();
     if (!commandUsage.isEmpty) {
-      print('');
-      print(commandUsage);
+      buffer.add('\n');
+      buffer.add(commandUsage);
     }
+
+    log.message(buffer.toString());
   }
 
   /// Returns the appropriate exit code for [exception], falling back on 1 if no
diff --git a/utils/pub/system_cache.dart b/utils/pub/system_cache.dart
index 932cbbb..ce913e0 100644
--- a/utils/pub/system_cache.dart
+++ b/utils/pub/system_cache.dart
@@ -10,6 +10,7 @@
 import 'hosted_source.dart';
 import 'io.dart';
 import 'io.dart' as io show createTempDir;
+import 'log.dart' as log;
 import 'package.dart';
 import 'sdk_source.dart';
 import 'source.dart';
@@ -102,6 +103,7 @@
 
   /// Delete's the system cache's internal temp directory.
   Future deleteTempDir() {
+    log.fine('Clean up system cache temp directory $tempDir.');
     return dirExists(tempDir).chain((exists) {
       if (!exists) return new Future.immediate(null);
       return deleteDir(tempDir);
diff --git a/utils/pub/validator.dart b/utils/pub/validator.dart
index 584a214..3e491a9 100644
--- a/utils/pub/validator.dart
+++ b/utils/pub/validator.dart
@@ -5,9 +5,12 @@
 library validator;
 
 import 'entrypoint.dart';
+import 'log.dart' as log;
 import 'io.dart';
 import 'system_cache.dart';
 import 'utils.dart';
+import 'validator/lib.dart';
+import 'validator/license.dart';
 import 'validator/name.dart';
 import 'validator/pubspec_field.dart';
 
@@ -38,6 +41,8 @@
   static Future<Pair<List<String>, List<String>>> runAll(
       Entrypoint entrypoint) {
     var validators = [
+      new LibValidator(entrypoint),
+      new LicenseValidator(entrypoint),
       new NameValidator(entrypoint),
       new PubspecFieldValidator(entrypoint)
     ];
@@ -52,19 +57,19 @@
       var warnings = flatten(validators.map((validator) => validator.warnings));
 
       if (!errors.isEmpty) {
-        printError("== Errors:");
+        log.error("== Errors:");
         for (var error in errors) {
-          printError("* $error");
+          log.error("* $error");
         }
-        printError("");
+        log.error("");
       }
 
       if (!warnings.isEmpty) {
-        printError("== Warnings:");
+        log.warning("== Warnings:");
         for (var warning in warnings) {
-          printError("* $warning");
+          log.warning("* $warning");
         }
-        printError("");
+        log.warning("");
       }
 
       return new Pair<List<String>, List<String>>(errors, warnings);
diff --git a/utils/pub/validator/lib.dart b/utils/pub/validator/lib.dart
new file mode 100644
index 0000000..64f44c6
--- /dev/null
+++ b/utils/pub/validator/lib.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library lib_validator;
+
+import 'dart:io';
+
+import '../entrypoint.dart';
+import '../io.dart';
+import '../system_cache.dart';
+import '../utils.dart';
+import '../validator.dart';
+
+// TODO(nweiz): When issue 7196 is fixed, complain about non-Dart files in lib.
+/// A validator that checks that libraries in "lib/" (and not "lib/src/") exist
+/// and are well-formed.
+class LibValidator extends Validator {
+  LibValidator(Entrypoint entrypoint)
+    : super(entrypoint);
+
+  Future validate() {
+    var libDir = join(entrypoint.root.dir, "lib");
+    return dirExists(libDir).chain((libDirExists) {
+      if (!libDirExists) {
+        errors.add('Your package must have a "lib/" directory so users have '
+            'something to import.');
+        return new Future.immediate(null);
+      }
+
+      return listDir(libDir).transform((files) {
+        files = files.map((file) => relativeTo(file, libDir));
+        if (files.isEmpty) {
+          errors.add('The "lib/" directory may not be empty so users have '
+              'something to import');
+        } else if (files.length == 1 && files.first == "src") {
+          errors.add('The "lib/" directory must contain something other than '
+              '"src/" so users have something to import');
+        }
+      });
+    });
+  }
+}
diff --git a/utils/pub/validator/license.dart b/utils/pub/validator/license.dart
new file mode 100644
index 0000000..46a1c40
--- /dev/null
+++ b/utils/pub/validator/license.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pubspec_field_validator;
+
+import '../entrypoint.dart';
+import '../io.dart';
+import '../system_cache.dart';
+import '../validator.dart';
+
+/// A validator that checks that a LICENSE-like file exists.
+class LicenseValidator extends Validator {
+  LicenseValidator(Entrypoint entrypoint)
+    : super(entrypoint);
+
+  Future validate() {
+    return listDir(entrypoint.root.dir).transform((files) {
+      var licenseLike = new RegExp(
+          r"^([a-zA-Z0-9]+[-_])?(LICENSE|COPYING)(\..*)?$");
+      if (files.map(basename).some(licenseLike.hasMatch)) return;
+
+      errors.add("Your package must have a COPYING or LICENSE file containing "
+          "an open-source license. For more details, see "
+          "http://pub.dartlang.org/doc/pub-lish.html.");
+    });
+  }
+}
diff --git a/utils/pub/validator/name.dart b/utils/pub/validator/name.dart
index 93c08ae..ecc34e4 100644
--- a/utils/pub/validator/name.dart
+++ b/utils/pub/validator/name.dart
@@ -8,6 +8,7 @@
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../path.dart' as path;
 import '../validator.dart';
 
 /// Dart reserved words, from the Dart spec.
@@ -31,11 +32,10 @@
       return listDir(libDir, recursive: true);
     }).transform((files) {
       for (var file in files) {
-        // TODO(nweiz): Since `file` is absolute, this will break if the package
-        // itself is in a directory named "src" (issue 7215).
+        file = relativeTo(file, libDir);
         if (splitPath(file).contains("src")) continue;
-        if (new Path(file).extension != 'dart') continue;
-        var libName = new Path(basename(file)).filenameWithoutExtension;
+        if (path.extension(file) != '.dart') continue;
+        var libName = path.basenameWithoutExtension(file);
         _checkName(libName, 'The name of "$file", "$libName",');
       }
     });
diff --git a/utils/pub/version_solver.dart b/utils/pub/version_solver.dart
index 31baa9c..1a84aa2 100644
--- a/utils/pub/version_solver.dart
+++ b/utils/pub/version_solver.dart
@@ -40,6 +40,7 @@
 import 'dart:json';
 import 'dart:math';
 import 'lock_file.dart';
+import 'log.dart' as log;
 import 'package.dart';
 import 'pubspec.dart';
 import 'root_source.dart';
@@ -59,7 +60,7 @@
  */
 Future<List<PackageId>> resolveVersions(SourceRegistry sources, Package root,
     LockFile lockFile) {
-  print('Resolving dependencies...');
+  log.message('Resolving dependencies...');
   return new VersionSolver(sources, root, lockFile).solve();
 }
 
@@ -267,6 +268,8 @@
   }
 
   Future process(VersionSolver solver) {
+    log.fine("Changing $package to version $version.");
+
     var dependency = solver.getDependency(package);
     var oldVersion = dependency.version;
     solver.setVersion(package, version);
@@ -418,6 +421,8 @@
   AddConstraint(this.depender, this.ref);
 
   Future process(VersionSolver solver) {
+    log.fine("Adding $depender's constraint $ref.");
+
     var dependency = solver.getDependency(ref.name);
     var oldDependency = dependency.clone();
     dependency.placeConstraint(depender, ref);
@@ -449,6 +454,8 @@
   RemoveConstraint(this.depender, this.dependent);
 
   Future process(VersionSolver solver) {
+    log.fine("Removing $depender's constraint ($_removed) on $dependent.");
+
     var dependency = solver.getDependency(dependent);
     var oldDependency = dependency.clone();
     _removed = dependency.removeConstraint(depender);
@@ -468,6 +475,8 @@
   UnlockPackage(this.package);
 
   Future process(VersionSolver solver) {
+    log.fine("Unlocking ${package.name}.");
+
     solver.lockFile.packages.remove(package.name);
     return solver.getBestVersion(package).transform((best) {
       if (best == null) return null;
diff --git a/utils/tests/pub/oauth2_test.dart b/utils/tests/pub/oauth2_test.dart
index e739a96..32e4a75 100644
--- a/utils/tests/pub/oauth2_test.dart
+++ b/utils/tests/pub/oauth2_test.dart
@@ -15,7 +15,7 @@
 import '../../pub/utils.dart';
 
 main() {
-  setUp(() => dir(appPath, [libPubspec("test_pkg", "1.0.0")]).scheduleCreate());
+  setUp(() => normalPackage.scheduleCreate());
 
   test('with no credentials.json, authenticates and saves credentials.json',
       () {
@@ -27,7 +27,7 @@
       expect(request.headers.value('authorization'),
           equals('Bearer access token'));
 
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     pub.kill();
@@ -46,7 +46,7 @@
       expect(request.headers.value('authorization'),
           equals('Bearer access token'));
 
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     pub.kill();
@@ -83,7 +83,7 @@
       expect(request.headers.value('authorization'),
           equals('Bearer new access token'));
 
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     pub.shouldExit();
@@ -111,7 +111,7 @@
       expect(request.headers.value('authorization'),
           equals('Bearer new access token'));
 
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     pub.kill();
@@ -135,7 +135,7 @@
       expect(request.headers.value('authorization'),
           equals('Bearer new access token'));
 
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     pub.kill();
diff --git a/utils/tests/pub/path/path_posix_test.dart b/utils/tests/pub/path/path_posix_test.dart
new file mode 100644
index 0000000..a34c32d
--- /dev/null
+++ b/utils/tests/pub/path/path_posix_test.dart
@@ -0,0 +1,284 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library path_test;
+
+import 'dart:io' as io;
+
+import '../../../../pkg/unittest/lib/unittest.dart';
+import '../../../pub/path.dart' as path;
+
+main() {
+  var builder = new path.Builder(style: path.Style.posix, root: '/root/path');
+
+  if (new path.Builder().style == path.Style.posix) {
+    group('absolute', () {
+      expect(path.absolute('a/b.txt'), path.join(path.current, 'a/b.txt'));
+      expect(path.absolute('/a/b.txt'), '/a/b.txt');
+    });
+  }
+
+  test('separator', () {
+    expect(builder.separator, '/');
+  });
+
+  test('extension', () {
+    expect(builder.extension(''), '');
+    expect(builder.extension('foo.dart'), '.dart');
+    expect(builder.extension('foo.dart.js'), '.js');
+    expect(builder.extension('a.b/c'), '');
+    expect(builder.extension('a.b/c.d'), '.d');
+    expect(builder.extension('~/.bashrc'), '');
+    expect(builder.extension(r'a.b\c'), r'.b\c');
+  });
+
+  test('basename', () {
+    expect(builder.basename(''), '');
+    expect(builder.basename('a'), 'a');
+    expect(builder.basename('a/b'), 'b');
+    expect(builder.basename('a/b/c'), 'c');
+    expect(builder.basename('a/b.c'), 'b.c');
+    expect(builder.basename('a/'), '');
+    expect(builder.basename('a/.'), '.');
+    expect(builder.basename(r'a/b\c'), r'b\c');
+  });
+
+  test('basenameWithoutExtension', () {
+    expect(builder.basenameWithoutExtension(''), '');
+    expect(builder.basenameWithoutExtension('a'), 'a');
+    expect(builder.basenameWithoutExtension('a/b'), 'b');
+    expect(builder.basenameWithoutExtension('a/b/c'), 'c');
+    expect(builder.basenameWithoutExtension('a/b.c'), 'b');
+    expect(builder.basenameWithoutExtension('a/'), '');
+    expect(builder.basenameWithoutExtension('a/.'), '.');
+    expect(builder.basenameWithoutExtension(r'a/b\c'), r'b\c');
+    expect(builder.basenameWithoutExtension('a/.bashrc'), '.bashrc');
+    expect(builder.basenameWithoutExtension('a/b/c.d.e'), 'c.d');
+  });
+
+  test('isAbsolute', () {
+    expect(builder.isAbsolute(''), false);
+    expect(builder.isAbsolute('a'), false);
+    expect(builder.isAbsolute('a/b'), false);
+    expect(builder.isAbsolute('/a'), true);
+    expect(builder.isAbsolute('/a/b'), true);
+    expect(builder.isAbsolute('~'), false);
+    expect(builder.isAbsolute('.'), false);
+    expect(builder.isAbsolute('../a'), false);
+    expect(builder.isAbsolute('C:/a'), false);
+    expect(builder.isAbsolute(r'C:\a'), false);
+    expect(builder.isAbsolute(r'\\a'), false);
+  });
+
+  test('isRelative', () {
+    expect(builder.isRelative(''), true);
+    expect(builder.isRelative('a'), true);
+    expect(builder.isRelative('a/b'), true);
+    expect(builder.isRelative('/a'), false);
+    expect(builder.isRelative('/a/b'), false);
+    expect(builder.isRelative('~'), true);
+    expect(builder.isRelative('.'), true);
+    expect(builder.isRelative('../a'), true);
+    expect(builder.isRelative('C:/a'), true);
+    expect(builder.isRelative(r'C:\a'), true);
+    expect(builder.isRelative(r'\\a'), true);
+  });
+
+  group('join', () {
+    test('allows up to eight parts', () {
+      expect(builder.join('a'), 'a');
+      expect(builder.join('a', 'b'), 'a/b');
+      expect(builder.join('a', 'b', 'c'), 'a/b/c');
+      expect(builder.join('a', 'b', 'c', 'd'), 'a/b/c/d');
+      expect(builder.join('a', 'b', 'c', 'd', 'e'), 'a/b/c/d/e');
+      expect(builder.join('a', 'b', 'c', 'd', 'e', 'f'), 'a/b/c/d/e/f');
+      expect(builder.join('a', 'b', 'c', 'd', 'e', 'f', 'g'), 'a/b/c/d/e/f/g');
+      expect(builder.join('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'),
+          'a/b/c/d/e/f/g/h');
+    });
+
+    test('does not add separator if a part ends in one', () {
+      expect(builder.join('a/', 'b', 'c/', 'd'), 'a/b/c/d');
+      expect(builder.join('a\\', 'b'), r'a\/b');
+    });
+
+    test('ignores parts before an absolute path', () {
+      expect(builder.join('a', '/b', '/c', 'd'), '/c/d');
+      expect(builder.join('a', r'c:\b', 'c', 'd'), r'a/c:\b/c/d');
+      expect(builder.join('a', r'\\b', 'c', 'd'), r'a/\\b/c/d');
+    });
+  });
+
+  group('normalize', () {
+    test('simple cases', () {
+      expect(builder.normalize(''), '');
+      expect(builder.normalize('.'), '.');
+      expect(builder.normalize('..'), '..');
+      expect(builder.normalize('a'), 'a');
+      expect(builder.normalize('/'), '/');
+      expect(builder.normalize(r'\'), r'\');
+    });
+
+    test('collapses redundant separators', () {
+      expect(builder.normalize(r'a/b/c'), r'a/b/c');
+      expect(builder.normalize(r'a//b///c////d'), r'a/b/c/d');
+    });
+
+    test('does not collapse separators for other platform', () {
+      expect(builder.normalize(r'a\\b\\\c'), r'a\\b\\\c');
+    });
+
+    test('eliminates "." parts', () {
+      expect(builder.normalize('./'), '.');
+      expect(builder.normalize('/.'), '/');
+      expect(builder.normalize('/./'), '/');
+      expect(builder.normalize('./.'), '.');
+      expect(builder.normalize('a/./b'), 'a/b');
+      expect(builder.normalize('a/.b/c'), 'a/.b/c');
+      expect(builder.normalize('a/././b/./c'), 'a/b/c');
+      expect(builder.normalize('././a'), 'a');
+      expect(builder.normalize('a/./.'), 'a');
+    });
+
+    test('eliminates ".." parts', () {
+      expect(builder.normalize('..'), '..');
+      expect(builder.normalize('../'), '..');
+      expect(builder.normalize('../../..'), '../../..');
+      expect(builder.normalize('../../../'), '../../..');
+      expect(builder.normalize('/..'), '/');
+      expect(builder.normalize('/../../..'), '/');
+      expect(builder.normalize('/../../../a'), '/a');
+      expect(builder.normalize('a/..'), '.');
+      expect(builder.normalize('a/b/..'), 'a');
+      expect(builder.normalize('a/../b'), 'b');
+      expect(builder.normalize('a/./../b'), 'b');
+      expect(builder.normalize('a/b/c/../../d/e/..'), 'a/d');
+      expect(builder.normalize('a/b/../../../../c'), '../../c');
+    });
+
+    test('does not walk before root on absolute paths', () {
+      expect(builder.normalize('..'), '..');
+      expect(builder.normalize('../'), '..');
+      expect(builder.normalize('/..'), '/');
+      expect(builder.normalize('a/..'), '.');
+      expect(builder.normalize('a/b/..'), 'a');
+      expect(builder.normalize('a/../b'), 'b');
+      expect(builder.normalize('a/./../b'), 'b');
+      expect(builder.normalize('a/b/c/../../d/e/..'), 'a/d');
+      expect(builder.normalize('a/b/../../../../c'), '../../c');
+    });
+
+    test('removes trailing separators', () {
+      expect(builder.normalize('./'), '.');
+      expect(builder.normalize('.//'), '.');
+      expect(builder.normalize('a/'), 'a');
+      expect(builder.normalize('a/b/'), 'a/b');
+      expect(builder.normalize('a/b///'), 'a/b');
+    });
+  });
+
+  group('relative', () {
+    group('from absolute root', () {
+      test('given absolute path in root', () {
+        expect(builder.relative('/'), '../..');
+        expect(builder.relative('/root'), '..');
+        expect(builder.relative('/root/path'), '.');
+        expect(builder.relative('/root/path/a'), 'a');
+        expect(builder.relative('/root/path/a/b.txt'), 'a/b.txt');
+        expect(builder.relative('/root/a/b.txt'), '../a/b.txt');
+      });
+
+      test('given absolute path outside of root', () {
+        expect(builder.relative('/a/b'), '../../a/b');
+        expect(builder.relative('/root/path/a'), 'a');
+        expect(builder.relative('/root/path/a/b.txt'), 'a/b.txt');
+        expect(builder.relative('/root/a/b.txt'), '../a/b.txt');
+      });
+
+      test('given relative path', () {
+        // The path is considered relative to the root, so it basically just
+        // normalizes.
+        expect(builder.relative(''), '.');
+        expect(builder.relative('.'), '.');
+        expect(builder.relative('a'), 'a');
+        expect(builder.relative('a/b.txt'), 'a/b.txt');
+        expect(builder.relative('../a/b.txt'), '../a/b.txt');
+        expect(builder.relative('a/./b/../c.txt'), 'a/c.txt');
+      });
+    });
+
+    group('from relative root', () {
+      var r = new path.Builder(style: path.Style.posix, root: 'foo/bar');
+
+      // These tests rely on the current working directory, so don't do the
+      // right thing if you run them on the wrong platform.
+      if (io.Platform.operatingSystem != 'windows') {
+        test('given absolute path', () {
+          var b = new path.Builder(style: path.Style.posix);
+          expect(r.relative('/'), b.join(b.relative('/'), '../..'));
+          expect(r.relative('/a/b'), b.join(b.relative('/'), '../../a/b'));
+        });
+      }
+
+      test('given relative path', () {
+        // The path is considered relative to the root, so it basically just
+        // normalizes.
+        expect(r.relative(''), '.');
+        expect(r.relative('.'), '.');
+        expect(r.relative('..'), '..');
+        expect(r.relative('a'), 'a');
+        expect(r.relative('a/b.txt'), 'a/b.txt');
+        expect(r.relative('../a/b.txt'), '../a/b.txt');
+        expect(r.relative('a/./b/../c.txt'), 'a/c.txt');
+      });
+    });
+
+    test('from a root with extension', () {
+      var r = new path.Builder(style: path.Style.posix, root: '/dir.ext');
+      expect(r.relative('/dir.ext/file'), 'file');
+    });
+  });
+
+  group('resolve', () {
+    test('allows up to seven parts', () {
+      expect(builder.resolve('a'), '/root/path/a');
+      expect(builder.resolve('a', 'b'), '/root/path/a/b');
+      expect(builder.resolve('a', 'b', 'c'), '/root/path/a/b/c');
+      expect(builder.resolve('a', 'b', 'c', 'd'), '/root/path/a/b/c/d');
+      expect(builder.resolve('a', 'b', 'c', 'd', 'e'), '/root/path/a/b/c/d/e');
+      expect(builder.resolve('a', 'b', 'c', 'd', 'e', 'f'),
+          '/root/path/a/b/c/d/e/f');
+      expect(builder.resolve('a', 'b', 'c', 'd', 'e', 'f', 'g'),
+          '/root/path/a/b/c/d/e/f/g');
+    });
+
+    test('does not add separator if a part ends in one', () {
+      expect(builder.resolve('a/', 'b', 'c/', 'd'), '/root/path/a/b/c/d');
+      expect(builder.resolve(r'a\', 'b'), r'/root/path/a\/b');
+    });
+
+    test('ignores parts before an absolute path', () {
+      expect(builder.resolve('a', '/b', '/c', 'd'), '/c/d');
+      expect(builder.resolve('a', r'c:\b', 'c', 'd'), r'/root/path/a/c:\b/c/d');
+      expect(builder.resolve('a', r'\\b', 'c', 'd'), r'/root/path/a/\\b/c/d');
+    });
+  });
+
+  test('withoutExtension', () {
+    expect(builder.withoutExtension(''), '');
+    expect(builder.withoutExtension('a'), 'a');
+    expect(builder.withoutExtension('.a'), '.a');
+    expect(builder.withoutExtension('a.b'), 'a');
+    expect(builder.withoutExtension('a/b.c'), 'a/b');
+    expect(builder.withoutExtension('a/b.c.d'), 'a/b.c');
+    expect(builder.withoutExtension('a/'), 'a/');
+    expect(builder.withoutExtension('a/b/'), 'a/b/');
+    expect(builder.withoutExtension('a/.'), 'a/.');
+    expect(builder.withoutExtension('a/.b'), 'a/.b');
+    expect(builder.withoutExtension('a.b/c'), 'a.b/c');
+    expect(builder.withoutExtension(r'a.b\c'), r'a');
+    expect(builder.withoutExtension(r'a/b\c'), r'a/b\c');
+    expect(builder.withoutExtension(r'a/b\c.d'), r'a/b\c');
+  });
+}
diff --git a/utils/tests/pub/path/path_test.dart b/utils/tests/pub/path/path_test.dart
new file mode 100644
index 0000000..26812a1
--- /dev/null
+++ b/utils/tests/pub/path/path_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library all_test;
+
+import 'dart:io' as io;
+
+import '../../../../pkg/unittest/lib/unittest.dart';
+import '../../../pub/path.dart' as path;
+
+main() {
+  group('path.Style', () {
+    test('name', () {
+      expect(path.Style.posix.name, 'posix');
+      expect(path.Style.windows.name, 'windows');
+    });
+
+    test('separator', () {
+      expect(path.Style.posix.separator, '/');
+      expect(path.Style.windows.separator, '\\');
+    });
+
+    test('toString()', () {
+      expect(path.Style.posix.toString(), 'posix');
+      expect(path.Style.windows.toString(), 'windows');
+    });
+  });
+
+  group('new Builder()', () {
+    test('uses the given root directory', () {
+      var builder = new path.Builder(root: '/a/b/c');
+      expect(builder.root, '/a/b/c');
+    });
+
+    test('uses the given style', () {
+      var builder = new path.Builder(style: path.Style.windows);
+      expect(builder.style, path.Style.windows);
+    });
+
+    test('uses the current working directory if root is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.root, new io.Directory.current().path);
+    });
+
+    test('uses the host OS if style is omitted', () {
+      var builder = new path.Builder();
+      if (io.Platform.operatingSystem == 'windows') {
+        expect(builder.style, path.Style.windows);
+      } else {
+        expect(builder.style, path.Style.posix);
+      }
+    });
+  });
+
+  test('current', () {
+    expect(path.current, new io.Directory.current().path);
+  });
+}
diff --git a/utils/tests/pub/path/path_windows_test.dart b/utils/tests/pub/path/path_windows_test.dart
new file mode 100644
index 0000000..1861a67
--- /dev/null
+++ b/utils/tests/pub/path/path_windows_test.dart
@@ -0,0 +1,311 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library path_test;
+
+import 'dart:io' as io;
+
+import '../../../../pkg/unittest/lib/unittest.dart';
+import '../../../pub/path.dart' as path;
+
+main() {
+  var builder = new path.Builder(style: path.Style.windows,
+                                 root: r'C:\root\path');
+
+  if (new path.Builder().style == path.Style.windows) {
+    group('absolute', () {
+      expect(path.absolute(r'a\b.txt'), path.join(path.current, r'a\b.txt'));
+      expect(path.absolute(r'C:\a\b.txt'), r'C:\a\b.txt');
+      expect(path.absolute(r'\\a\b.txt'), r'\\a\b.txt');
+    });
+  }
+
+  group('separator', () {
+    expect(builder.separator, '\\');
+  });
+
+  test('extension', () {
+    expect(builder.extension(''), '');
+    expect(builder.extension('foo.dart'), '.dart');
+    expect(builder.extension('foo.dart.js'), '.js');
+    expect(builder.extension(r'a.b\c'), '');
+    expect(builder.extension('a.b/c.d'), '.d');
+    expect(builder.extension(r'~\.bashrc'), '');
+    expect(builder.extension(r'a.b/c'), r'');
+  });
+
+  test('basename', () {
+    expect(builder.basename(r''), '');
+    expect(builder.basename(r'a'), 'a');
+    expect(builder.basename(r'a\b'), 'b');
+    expect(builder.basename(r'a\b\c'), 'c');
+    expect(builder.basename(r'a\b.c'), 'b.c');
+    expect(builder.basename(r'a\'), '');
+    expect(builder.basename(r'a/'), '');
+    expect(builder.basename(r'a\.'), '.');
+    expect(builder.basename(r'a\b/c'), r'c');
+  });
+
+  test('basenameWithoutExtension', () {
+    expect(builder.basenameWithoutExtension(''), '');
+    expect(builder.basenameWithoutExtension('a'), 'a');
+    expect(builder.basenameWithoutExtension(r'a\b'), 'b');
+    expect(builder.basenameWithoutExtension(r'a\b\c'), 'c');
+    expect(builder.basenameWithoutExtension(r'a\b.c'), 'b');
+    expect(builder.basenameWithoutExtension(r'a\'), '');
+    expect(builder.basenameWithoutExtension(r'a\.'), '.');
+    expect(builder.basenameWithoutExtension(r'a\b/c'), r'c');
+    expect(builder.basenameWithoutExtension(r'a\.bashrc'), '.bashrc');
+    expect(builder.basenameWithoutExtension(r'a\b\c.d.e'), 'c.d');
+  });
+
+  test('isAbsolute', () {
+    expect(builder.isAbsolute(''), false);
+    expect(builder.isAbsolute('a'), false);
+    expect(builder.isAbsolute(r'a\b'), false);
+    expect(builder.isAbsolute(r'\a'), false);
+    expect(builder.isAbsolute(r'\a\b'), false);
+    expect(builder.isAbsolute('~'), false);
+    expect(builder.isAbsolute('.'), false);
+    expect(builder.isAbsolute(r'..\a'), false);
+    expect(builder.isAbsolute(r'a:/a\b'), true);
+    expect(builder.isAbsolute(r'D:/a/b'), true);
+    expect(builder.isAbsolute(r'c:\'), true);
+    expect(builder.isAbsolute(r'B:\'), true);
+    expect(builder.isAbsolute(r'c:\a'), true);
+    expect(builder.isAbsolute(r'C:\a'), true);
+    expect(builder.isAbsolute(r'\\a'), true);
+    expect(builder.isAbsolute(r'\\'), true);
+  });
+
+  test('isRelative', () {
+    expect(builder.isRelative(''), true);
+    expect(builder.isRelative('a'), true);
+    expect(builder.isRelative(r'a\b'), true);
+    expect(builder.isRelative(r'\a'), true);
+    expect(builder.isRelative(r'\a\b'), true);
+    expect(builder.isRelative('~'), true);
+    expect(builder.isRelative('.'), true);
+    expect(builder.isRelative(r'..\a'), true);
+    expect(builder.isRelative(r'a:/a\b'), false);
+    expect(builder.isRelative(r'D:/a/b'), false);
+    expect(builder.isRelative(r'c:\'), false);
+    expect(builder.isRelative(r'B:\'), false);
+    expect(builder.isRelative(r'c:\a'), false);
+    expect(builder.isRelative(r'C:\a'), false);
+    expect(builder.isRelative(r'\\a'), false);
+    expect(builder.isRelative(r'\\'), false);
+  });
+
+  group('join', () {
+    test('allows up to eight parts', () {
+      expect(builder.join('a'), 'a');
+      expect(builder.join('a', 'b'), r'a\b');
+      expect(builder.join('a', 'b', 'c'), r'a\b\c');
+      expect(builder.join('a', 'b', 'c', 'd'), r'a\b\c\d');
+      expect(builder.join('a', 'b', 'c', 'd', 'e'), r'a\b\c\d\e');
+      expect(builder.join('a', 'b', 'c', 'd', 'e', 'f'), r'a\b\c\d\e\f');
+      expect(builder.join('a', 'b', 'c', 'd', 'e', 'f', 'g'), r'a\b\c\d\e\f\g');
+      expect(builder.join('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'),
+          r'a\b\c\d\e\f\g\h');
+    });
+
+    test('does not add separator if a part ends or begins in one', () {
+      expect(builder.join(r'a\', 'b', r'c\', 'd'), r'a\b\c\d');
+      expect(builder.join('a/', 'b'), r'a/b');
+      expect(builder.join('a', '/b'), 'a/b');
+      expect(builder.join('a', r'\b'), r'a\b');
+    });
+
+    test('ignores parts before an absolute path', () {
+      expect(builder.join('a', '/b', '/c', 'd'), r'a/b/c\d');
+      expect(builder.join('a', r'c:\b', 'c', 'd'), r'c:\b\c\d');
+      expect(builder.join('a', r'\\b', r'\\c', 'd'), r'\\c\d');
+    });
+  });
+
+  group('normalize', () {
+    test('simple cases', () {
+      expect(builder.normalize(''), '');
+      expect(builder.normalize('.'), '.');
+      expect(builder.normalize('..'), '..');
+      expect(builder.normalize('a'), 'a');
+      expect(builder.normalize('C:/'), r'C:/');
+      expect(builder.normalize(r'C:\'), r'C:\');
+      expect(builder.normalize(r'\\'), r'\\');
+    });
+
+    test('collapses redundant separators', () {
+      expect(builder.normalize(r'a\b\c'), r'a\b\c');
+      expect(builder.normalize(r'a\\b\\\c\\\\d'), r'a\b\c\d');
+    });
+
+    test('eliminates "." parts', () {
+      expect(builder.normalize(r'.\'), '.');
+      expect(builder.normalize(r'c:\.'), r'c:\');
+      expect(builder.normalize(r'B:\.\'), r'B:\');
+      expect(builder.normalize(r'\\.'), r'\\');
+      expect(builder.normalize(r'\\.\'), r'\\');
+      expect(builder.normalize(r'.\.'), '.');
+      expect(builder.normalize(r'a\.\b'), r'a\b');
+      expect(builder.normalize(r'a\.b\c'), r'a\.b\c');
+      expect(builder.normalize(r'a\./.\b\.\c'), r'a\b\c');
+      expect(builder.normalize(r'.\./a'), 'a');
+      expect(builder.normalize(r'a/.\.'), 'a');
+    });
+
+    test('eliminates ".." parts', () {
+      expect(builder.normalize('..'), '..');
+      expect(builder.normalize(r'..\'), '..');
+      expect(builder.normalize(r'..\..\..'), r'..\..\..');
+      expect(builder.normalize(r'../..\..\'), r'..\..\..');
+      // TODO(rnystrom): Is this how Python handles absolute paths on Windows?
+      expect(builder.normalize(r'\\..'), r'\\');
+      expect(builder.normalize(r'\\..\..\..'), r'\\');
+      expect(builder.normalize(r'\\..\../..\a'), r'\\a');
+      expect(builder.normalize(r'c:\..'), r'c:\');
+      expect(builder.normalize(r'A:/..\..\..'), r'A:/');
+      expect(builder.normalize(r'b:\..\..\..\a'), r'b:\a');
+      expect(builder.normalize(r'a\..'), '.');
+      expect(builder.normalize(r'a\b\..'), 'a');
+      expect(builder.normalize(r'a\..\b'), 'b');
+      expect(builder.normalize(r'a\.\..\b'), 'b');
+      expect(builder.normalize(r'a\b\c\..\..\d\e\..'), r'a\d');
+      expect(builder.normalize(r'a\b\..\..\..\..\c'), r'..\..\c');
+    });
+
+    test('removes trailing separators', () {
+      expect(builder.normalize(r'.\'), '.');
+      expect(builder.normalize(r'.\\'), '.');
+      expect(builder.normalize(r'a/'), 'a');
+      expect(builder.normalize(r'a\b\'), r'a\b');
+      expect(builder.normalize(r'a\b\\\'), r'a\b');
+    });
+
+    test('normalizes separators', () {
+      expect(builder.normalize(r'a/b\c'), r'a\b\c');
+    });
+  });
+
+  group('relative', () {
+    group('from absolute root', () {
+      test('given absolute path in root', () {
+        expect(builder.relative(r'C:\'), r'..\..');
+        expect(builder.relative(r'C:\root'), '..');
+        expect(builder.relative(r'C:\root\path'), '.');
+        expect(builder.relative(r'C:\root\path\a'), 'a');
+        expect(builder.relative(r'C:\root\path\a\b.txt'), r'a\b.txt');
+        expect(builder.relative(r'C:\root\a\b.txt'), r'..\a\b.txt');
+      });
+
+      test('given absolute path outside of root', () {
+        expect(builder.relative(r'C:\a\b'), r'..\..\a\b');
+        expect(builder.relative(r'C:\root\path\a'), 'a');
+        expect(builder.relative(r'C:\root\path\a\b.txt'), r'a\b.txt');
+        expect(builder.relative(r'C:\root\a\b.txt'), r'..\a\b.txt');
+      });
+
+      test('given absolute path on different drive', () {
+        expect(builder.relative(r'D:\a\b'), r'D:\a\b');
+      });
+
+      test('given relative path', () {
+        // The path is considered relative to the root, so it basically just
+        // normalizes.
+        expect(builder.relative(''), '.');
+        expect(builder.relative('.'), '.');
+        expect(builder.relative('a'), 'a');
+        expect(builder.relative(r'a\b.txt'), r'a\b.txt');
+        expect(builder.relative(r'..\a\b.txt'), r'..\a\b.txt');
+        expect(builder.relative(r'a\.\b\..\c.txt'), r'a\c.txt');
+      });
+    });
+
+    group('from relative root', () {
+      var r = new path.Builder(style: path.Style.windows, root: r'foo\bar');
+
+      // These tests rely on the current working directory, so don't do the
+      // right thing if you run them on the wrong platform.
+      if (io.Platform.operatingSystem == 'windows') {
+        test('given absolute path', () {
+          var b = new path.Builder(style: path.Style.windows);
+          // TODO(rnystrom): Use a path method here to get the root prefix
+          // when one exists.
+          var drive = path.current.substring(0, 3);
+          expect(r.relative(drive), b.join(b.relative(drive), r'..\..'));
+          expect(r.relative(b.join(drive, r'a\b')),
+              b.join(b.relative(drive), r'..\..\a\b'));
+
+          // TODO(rnystrom): Test behavior when drive letters differ.
+        });
+      }
+
+      test('given relative path', () {
+        // The path is considered relative to the root, so it basically just
+        // normalizes.
+        expect(r.relative(''), '.');
+        expect(r.relative('.'), '.');
+        expect(r.relative('..'), '..');
+        expect(r.relative('a'), 'a');
+        expect(r.relative(r'a\b.txt'), r'a\b.txt');
+        expect(r.relative(r'..\a/b.txt'), r'..\a\b.txt');
+        expect(r.relative(r'a\./b\../c.txt'), r'a\c.txt');
+      });
+    });
+
+    test('from a root with extension', () {
+      var r = new path.Builder(style: path.Style.windows, root: r'C:\dir.ext');
+      expect(r.relative(r'C:\dir.ext\file'), 'file');
+    });
+
+    test('given absolute with different root prefix', () {
+      expect(builder.relative(r'D:\a\b'), r'D:\a\b');
+      expect(builder.relative(r'\\a\b'), r'\\a\b');
+    });
+  });
+
+  group('resolve', () {
+    test('allows up to seven parts', () {
+      expect(builder.resolve('a'), r'C:\root\path\a');
+      expect(builder.resolve('a', 'b'), r'C:\root\path\a\b');
+      expect(builder.resolve('a', 'b', 'c'), r'C:\root\path\a\b\c');
+      expect(builder.resolve('a', 'b', 'c', 'd'), r'C:\root\path\a\b\c\d');
+      expect(builder.resolve('a', 'b', 'c', 'd', 'e'),
+          r'C:\root\path\a\b\c\d\e');
+      expect(builder.resolve('a', 'b', 'c', 'd', 'e', 'f'),
+          r'C:\root\path\a\b\c\d\e\f');
+      expect(builder.resolve('a', 'b', 'c', 'd', 'e', 'f', 'g'),
+          r'C:\root\path\a\b\c\d\e\f\g');
+    });
+
+    test('does not add separator if a part ends in one', () {
+      expect(builder.resolve(r'a\', 'b', r'c\', 'd'), r'C:\root\path\a\b\c\d');
+      expect(builder.resolve('a/', 'b'), r'C:\root\path\a/b');
+    });
+
+    test('ignores parts before an absolute path', () {
+      expect(builder.resolve('a', '/b', '/c', 'd'), r'C:\root\path\a/b/c\d');
+      expect(builder.resolve('a', r'c:\b', 'c', 'd'), r'c:\b\c\d');
+      expect(builder.resolve('a', r'\\b', r'\\c', 'd'), r'\\c\d');
+    });
+  });
+
+  test('withoutExtension', () {
+    expect(builder.withoutExtension(''), '');
+    expect(builder.withoutExtension('a'), 'a');
+    expect(builder.withoutExtension('.a'), '.a');
+    expect(builder.withoutExtension('a.b'), 'a');
+    expect(builder.withoutExtension(r'a\b.c'), r'a\b');
+    expect(builder.withoutExtension(r'a\b.c.d'), r'a\b.c');
+    expect(builder.withoutExtension(r'a\'), r'a\');
+    expect(builder.withoutExtension(r'a\b\'), r'a\b\');
+    expect(builder.withoutExtension(r'a\.'), r'a\.');
+    expect(builder.withoutExtension(r'a\.b'), r'a\.b');
+    expect(builder.withoutExtension(r'a.b\c'), r'a.b\c');
+    expect(builder.withoutExtension(r'a/b.c/d'), r'a/b.c/d');
+    expect(builder.withoutExtension(r'a\b/c'), r'a\b/c');
+    expect(builder.withoutExtension(r'a\b/c.d'), r'a\b/c');
+    expect(builder.withoutExtension(r'a.b/c'), r'a.b/c');
+  });
+}
diff --git a/utils/tests/pub/pub.status b/utils/tests/pub/pub.status
index 83a5ac5..de0fba4 100644
--- a/utils/tests/pub/pub.status
+++ b/utils/tests/pub/pub.status
@@ -10,6 +10,6 @@
 [ $runtime == drt || $runtime == dartium || $runtime == opera ]
 *: Skip
 
-# TODO(rnystrom): Figure out why this is failing or timing out (#7211).
-[ $system == windows ]
-pub_lish_test: Skip
+[ $system == macos ]
+validator_test: Fail # Issue 7330
+
diff --git a/utils/tests/pub/pub_lish_test.dart b/utils/tests/pub/pub_lish_test.dart
index 1bfa3d6..a947601 100644
--- a/utils/tests/pub/pub_lish_test.dart
+++ b/utils/tests/pub/pub_lish_test.dart
@@ -13,7 +13,7 @@
 
 void handleUploadForm(ScheduledServer server, [Map body]) {
   server.handle('GET', '/packages/versions/new.json', (request, response) {
-    return server.url.chain((url) {
+    return server.url.transform((url) {
       expect(request.headers.value('authorization'),
           equals('Bearer access token'));
 
@@ -29,7 +29,7 @@
 
       response.headers.contentType = new ContentType("application", "json");
       response.outputStream.writeString(JSON.stringify(body));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
   });
 }
@@ -38,16 +38,16 @@
   server.handle('POST', '/upload', (request, response) {
     // TODO(nweiz): Once a multipart/form-data parser in Dart exists, validate
     // that the request body is correctly formatted. See issue 6952.
-    return server.url.chain((url) {
+    return server.url.transform((url) {
       response.statusCode = 302;
       response.headers.set('location', url.resolve('/create').toString());
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
   });
 }
 
 main() {
-  setUp(() => dir(appPath, [libPubspec("test_pkg", "1.0.0")]).scheduleCreate());
+  setUp(() => normalPackage.scheduleCreate());
 
   test('archives and uploads a package', () {
     var server = new ScheduledServer();
@@ -60,7 +60,7 @@
       response.outputStream.writeString(JSON.stringify({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextLine(), equals('Package test_pkg 1.0.0 uploaded!'));
@@ -84,7 +84,7 @@
       response.outputStream.writeString(JSON.stringify({
         'error': {'message': 'your token sucks'}
       }));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('OAuth2 authorization failed (your '
@@ -145,7 +145,7 @@
       response.outputStream.writeString(JSON.stringify({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     pub.shouldExit(0);
@@ -165,7 +165,7 @@
       response.outputStream.writeString(JSON.stringify({
         'error': {'message': 'your request sucked'}
       }));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('your request sucked'));
@@ -181,7 +181,7 @@
 
     server.handle('GET', '/packages/versions/new.json', (request, response) {
       response.outputStream.writeString('{not json');
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('Invalid server response:'));
@@ -307,7 +307,7 @@
 
     server.handle('POST', '/upload', (request, response) {
       // don't set the location header
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('Failed to upload the package.'));
@@ -328,7 +328,7 @@
       response.outputStream.writeString(JSON.stringify({
         'error': {'message': 'Your package was too boring.'}
       }));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('Your package was too boring.'));
@@ -346,7 +346,7 @@
 
     server.handle('GET', '/create', (request, response) {
       response.outputStream.writeString('{not json');
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('Invalid server response:'));
@@ -367,7 +367,7 @@
     server.handle('GET', '/create', (request, response) {
       response.statusCode = 400;
       response.outputStream.writeString(JSON.stringify(body));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('Invalid server response:'));
@@ -387,7 +387,7 @@
     var body = {'success': 'Your package was awesome.'};
     server.handle('GET', '/create', (request, response) {
       response.outputStream.writeString(JSON.stringify(body));
-      return closeHttpResponse(request, response);
+      response.outputStream.close();
     });
 
     expectLater(pub.nextErrLine(), equals('Invalid server response:'));
diff --git a/utils/tests/pub/pub_test.dart b/utils/tests/pub/pub_test.dart
index aa5454a..4ad65ad 100644
--- a/utils/tests/pub/pub_test.dart
+++ b/utils/tests/pub/pub_test.dart
@@ -15,16 +15,23 @@
     Usage: pub command [arguments]
 
     Global options:
-    -h, --help          Prints this usage information
-        --version       Prints the version of Pub
-        --[no-]trace    Prints a stack trace when an error occurs
+    -h, --help            Print this usage information.
+        --version         Print pub version.
+        --[no-]trace      Print debugging information when an error occurs.
+        --verbosity       Control output verbosity.
+
+              [all]       All output including internal tracing messages are shown.
+              [io]        IO operations are also shown.
+              [normal]    Errors, warnings, and user messages are shown.
+
+    -v, --verbose         Shortcut for "--verbosity=all"
 
     Available commands:
-      help      display help information for Pub
-      install   install the current package's dependencies
-      publish   publish the current package to pub.dartlang.org
-      update    update the current package's dependencies to the latest versions
-      version   print Pub version
+      help      Display help information for Pub.
+      install   Install the current package's dependencies.
+      publish   Publish the current package to pub.dartlang.org.
+      update    Update the current package's dependencies to the latest versions.
+      version   Print pub version.
 
     Use "pub help [command]" for more information about a command.
     """;
@@ -75,13 +82,36 @@
         exitCode: 64);
   });
 
-  test('an unknown help command displays an error message', () {
-    runPub(args: ['help', 'quylthulg'],
-        error: '''
-        Could not find a command named "quylthulg".
-        Run "pub help" to see available commands.
-        ''',
-        exitCode: 64);
+  group('help', () {
+    test('shows help for a command', () {
+      runPub(args: ['help', 'install'],
+          output: '''
+            Install the current package's dependencies.
+
+            Usage: pub install
+            ''');
+    });
+
+    test('shows help for a command', () {
+      runPub(args: ['help', 'publish'],
+          output: '''
+            Publish the current package to pub.dartlang.org.
+
+            Usage: pub publish [options]
+            --server    The package server to which to upload this package
+                        (defaults to "https://pub.dartlang.org")
+            ''');
+    });
+
+    test('an unknown help command displays an error message', () {
+      runPub(args: ['help', 'quylthulg'],
+          error: '''
+            Could not find a command named "quylthulg".
+            Run "pub help" to see available commands.
+            ''',
+            exitCode: 64);
+    });
+
   });
 
   test('displays the current version', () =>
diff --git a/utils/tests/pub/test_pub.dart b/utils/tests/pub/test_pub.dart
index 433c14c..aa8e879 100644
--- a/utils/tests/pub/test_pub.dart
+++ b/utils/tests/pub/test_pub.dart
@@ -23,6 +23,7 @@
 import '../../pub/git_source.dart';
 import '../../pub/hosted_source.dart';
 import '../../pub/io.dart';
+import '../../pub/path.dart' as path;
 import '../../pub/sdk_source.dart';
 import '../../pub/system_cache.dart';
 import '../../pub/utils.dart';
@@ -108,7 +109,7 @@
         } catch (e) {
           response.statusCode = 404;
           response.contentLength = 0;
-          closeHttpResponse(request, response);
+          response.outputStream.close();
           return;
         }
 
@@ -117,14 +118,14 @@
           response.statusCode = 200;
           response.contentLength = data.length;
           response.outputStream.write(data);
-          closeHttpResponse(request, response);
+          response.outputStream.close();
         });
 
         future.handleException((e) {
           print("Exception while handling ${request.uri}: $e");
           response.statusCode = 500;
           response.reasonPhrase = e.message;
-          closeHttpResponse(request, response);
+          response.outputStream.close();
         });
       };
       _server.listen("127.0.0.1", 0);
@@ -221,6 +222,15 @@
 /** Converts [value] into a YAML string. */
 String yaml(value) => JSON.stringify(value);
 
+/// Describes a package that passes all validation.
+Descriptor get normalPackage => dir(appPath, [
+  libPubspec("test_pkg", "1.0.0"),
+  file("LICENSE", "Eh, do what you want."),
+  dir("lib", [
+    file("test_pkg.dart", "int i = 1;")
+  ])
+]);
+
 /**
  * Describes a file named `pubspec.yaml` with the given YAML-serialized
  * [contents], which should be a serializable object.
@@ -527,15 +537,15 @@
     // If an error occurs during testing, delete the sandbox, throw the error so
     // that the test framework sees it, then finally call asyncDone so that the
     // test framework knows we're done doing asynchronous stuff.
-    var future = _runScheduled(createdSandboxDir, _scheduledOnException)
+    var subFuture = _runScheduled(createdSandboxDir, _scheduledOnException)
         .chain((_) => cleanup());
-    future.handleException((e) {
+    subFuture.handleException((e) {
       print("Exception while cleaning up: $e");
-      print(future.stackTrace);
-      registerException(error, future.stackTrace);
+      print(subFuture.stackTrace);
+      registerException(error, subFuture.stackTrace);
       return true;
     });
-    future.then((_) => registerException(error, future.stackTrace));
+    subFuture.then((_) => registerException(error, future.stackTrace));
     return true;
   });
 
@@ -546,10 +556,10 @@
 
 /// Get the path to the root "util/test/pub" directory containing the pub tests.
 String get testDirectory {
-  var dir = new Path.fromNative(new Options().script);
-  while (dir.filename != 'pub') dir = dir.directoryPath;
+  var dir = new Options().script;
+  while (basename(dir) != 'pub') dir = dirname(dir);
 
-  return new File(dir.toNativePath()).fullPathSync();
+  return getFullPath(dir);
 }
 
 /**
@@ -639,14 +649,14 @@
     // Find the main pub entrypoint.
     var pubPath = fs.joinPaths(testDirectory, '../../pub/pub.dart');
 
-    var dartArgs =
-        ['--enable-type-checks', '--enable-asserts', pubPath, '--trace'];
+    var dartArgs = ['--checked', pubPath, '--trace'];
     dartArgs.addAll(args);
 
     var environment = {
       'PUB_CACHE': pathInSandbox(cachePath),
       'DART_SDK': pathInSandbox(sdkPath)
     };
+
     if (tokenEndpoint != null) {
       environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint.toString();
     }
@@ -1268,7 +1278,7 @@
   });
 }
 
-/// A matcher that matches a Pair.	
+/// A matcher that matches a Pair.
 Matcher pairOf(Matcher firstMatcher, Matcher lastMatcher) =>
    new _PairMatcher(firstMatcher, lastMatcher);
 
diff --git a/utils/tests/pub/validator_test.dart b/utils/tests/pub/validator_test.dart
index a975c3e..d9877eb 100644
--- a/utils/tests/pub/validator_test.dart
+++ b/utils/tests/pub/validator_test.dart
@@ -12,6 +12,8 @@
 import '../../pub/entrypoint.dart';
 import '../../pub/io.dart';
 import '../../pub/validator.dart';
+import '../../pub/validator/lib.dart';
+import '../../pub/validator/license.dart';
 import '../../pub/validator/name.dart';
 import '../../pub/validator/pubspec_field.dart';
 
@@ -27,19 +29,49 @@
   expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isNot(isEmpty)));
 }
 
-Validator pubspecField(Entrypoint entrypoint) =>
-  new PubspecFieldValidator(entrypoint);
+Validator lib(Entrypoint entrypoint) => new LibValidator(entrypoint);
+
+Validator license(Entrypoint entrypoint) => new LicenseValidator(entrypoint);
 
 Validator name(Entrypoint entrypoint) => new NameValidator(entrypoint);
 
+Validator pubspecField(Entrypoint entrypoint) =>
+  new PubspecFieldValidator(entrypoint);
+
+void scheduleNormalPackage() => normalPackage.scheduleCreate();
+
 main() {
   group('should consider a package valid if it', () {
+    setUp(scheduleNormalPackage);
+
     test('looks normal', () {
       dir(appPath, [libPubspec("test_pkg", "1.0.0")]).scheduleCreate();
+      expectNoValidationError(license);
       expectNoValidationError(pubspecField);
       run();
     });
 
+    test('has a COPYING file', () {
+      file(join(appPath, 'LICENSE'), '').scheduleDelete();
+      file(join(appPath, 'COPYING'), '').scheduleCreate();
+      expectNoValidationError(license);
+      run();
+    });
+
+    test('has a prefixed LICENSE file', () {
+      file(join(appPath, 'LICENSE'), '').scheduleDelete();
+      file(join(appPath, 'MIT_LICENSE'), '').scheduleCreate();
+      expectNoValidationError(license);
+      run();
+    });
+
+    test('has a suffixed LICENSE file', () {
+      file(join(appPath, 'LICENSE'), '').scheduleDelete();
+      file(join(appPath, 'LICENSE.md'), '').scheduleCreate();
+      expectNoValidationError(license);
+      run();
+    });
+
     test('has "authors" instead of "author"', () {
       var package = package("test_pkg", "1.0.0");
       package["authors"] = [package.remove("author")];
@@ -59,9 +91,22 @@
       expectNoValidationError(name);
       run();
     });
+
+    test('has a non-Dart file in lib', () {
+      dir(appPath, [
+        libPubspec("test_pkg", "1.0.0"),
+        dir("lib", [
+          file("thing.txt", "woo hoo")
+        ])
+      ]).scheduleCreate();
+      expectNoValidationError(lib);
+      run();
+    });
   });
 
   group('should consider a package invalid if it', () {
+    setUp(scheduleNormalPackage);
+
     test('is missing the "homepage" field', () {
       var package = package("test_pkg", "1.0.0");
       package.remove("homepage");
@@ -135,6 +180,12 @@
       run();
     });
 
+    test('has no LICENSE file', () {
+      file(join(appPath, 'LICENSE'), '').scheduleDelete();
+      expectValidationError(license);
+      run();
+    });
+
     test('has an empty package name', () {
       dir(appPath, [libPubspec("", "1.0.0")]).scheduleCreate();
       expectValidationError(name);
@@ -200,5 +251,28 @@
       expectValidationError(name);
       run();
     });
+
+    test('has no lib directory', () {
+      dir(join(appPath, "lib")).scheduleDelete();
+      expectValidationError(lib);
+      run();
+    });
+
+    test('has an empty lib directory', () {
+      file(join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete();
+      expectValidationError(lib);
+      run();
+    });
+
+    test('has a lib directory containing only src', () {
+      file(join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete();
+      dir(appPath, [
+        dir("lib", [
+          dir("src", [file("test_pkg.dart", "int i = 0;")])
+        ])
+      ]).scheduleCreate();
+      expectValidationError(lib);
+      run();
+    });
   });
 }