Version 0.5.8.0

svn merge -r 22574:22721 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@22725 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/lib/src/error.dart b/pkg/analyzer_experimental/lib/src/error.dart
index 668dedb..5485a0f 100644
--- a/pkg/analyzer_experimental/lib/src/error.dart
+++ b/pkg/analyzer_experimental/lib/src/error.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+library error;
 
 import 'dart:collection';
 import 'dart:io';
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
index 9c40c3b..cb9c473 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
@@ -1,7 +1,7 @@
 // This code was auto-generated, is not intended to be edited, and is subject to
 // significant change. Please see the README file for more information.
 
-library engine.sdk;
+library engine.sdk.io;
 
 import 'dart:io';
 import 'dart:uri';
diff --git a/pkg/analyzer_experimental/lib/src/utils.dart b/pkg/analyzer_experimental/lib/src/utils.dart
index bb4a66f..4ff702f 100644
--- a/pkg/analyzer_experimental/lib/src/utils.dart
+++ b/pkg/analyzer_experimental/lib/src/utils.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+library utils;
 
 import 'dart:io';
 import 'dart:uri';
diff --git a/pkg/intl/lib/date_format.dart b/pkg/intl/lib/date_format.dart
index d12b6fa..ce79f2f 100644
--- a/pkg/intl/lib/date_format.dart
+++ b/pkg/intl/lib/date_format.dart
@@ -101,11 +101,11 @@
  *
  *      Pattern                           Result
  *      ----------------                  -------
- *      new DateFormat.yMd()             -> 07/10/1996
- *      new DateFormat("yMd")            -> 07/10/1996
+ *      new DateFormat.yMd()             -> 7/10/1996
+ *      new DateFormat("yMd")            -> 7/10/1996
  *      new DateFormat.yMMMMd("en_US")   -> July 10, 1996
  *      new DateFormat("Hm", "en_US")    -> 12:08 PM
- *      new DateFormat.yMd().add_Hm()        -> 07/10/1996 12:08 PM
+ *      new DateFormat.yMd().add_Hm()    -> 7/10/1996 12:08 PM
  *
  * Explicit Pattern Syntax: Formats can also be specified with a pattern string.
  * The skeleton forms will resolve to explicit patterns of this form, but will
diff --git a/pkg/scheduled_test/lib/scheduled_process.dart b/pkg/scheduled_test/lib/scheduled_process.dart
index 45e5061..23370f1 100644
--- a/pkg/scheduled_test/lib/scheduled_process.dart
+++ b/pkg/scheduled_test/lib/scheduled_process.dart
@@ -95,16 +95,15 @@
     var stdoutWithCanceller = _lineStreamWithCanceller(
         _process.then((p) => p.stdout));
     _stdoutCanceller = stdoutWithCanceller.last;
-    var stdoutTee = tee(stdoutWithCanceller.first);
-    _stdout = stdoutTee.first;
-    _stdoutLog = stdoutTee.last;
+    _stdoutLog = stdoutWithCanceller.first;
 
     var stderrWithCanceller = _lineStreamWithCanceller(
         _process.then((p) => p.stderr));
     _stderrCanceller = stderrWithCanceller.last;
-    var stderrTee = tee(stderrWithCanceller.first);
-    _stderr = stderrTee.first;
-    _stderrLog = stderrTee.last;
+    _stderrLog = stderrWithCanceller.first;
+
+    _stdout = stdoutStream();
+    _stderr = stderrStream();
   }
 
   /// Updates [_description] to reflect [executable] and [arguments], which are
@@ -186,9 +185,15 @@
   /// Converts a stream of bytes to a stream of lines and returns that along
   /// with a [StreamCanceller] controlling it.
   Pair<Stream<String>, StreamCanceller> _lineStreamWithCanceller(
-      Future<Stream<int>> streamFuture) {
+      Future<Stream<List<int>>> streamFuture) {
     return streamWithCanceller(futureStream(streamFuture)
         .handleError((e) => currentSchedule.signalError(e))
+        .map((chunk) {
+      // Whenever the process produces any sort of output, reset the schedule's
+      // timer.
+      currentSchedule.heartbeat();
+      return chunk;
+    })
         .transform(new StringDecoder(_encoding))
         .transform(new LineTransformer()));
   }
@@ -266,6 +271,32 @@
         "reading the remaining stderr from process '$description'");
   }
 
+  /// Returns a stream that will emit anything the process emits via the
+  /// process's standard output from now on.
+  ///
+  /// This stream will be independent from any other methods that deal with
+  /// standard output, including other calls to [stdoutStream].
+  ///
+  /// This can be overridden by subclasses to return a derived standard output
+  /// stream. This stream will then be used for [nextLine], [nextErrLine],
+  /// [remainingStdout], and [remainingStderr].
+  Stream<String> stdoutStream() {
+    var pair = tee(_stdoutLog);
+    _stdoutLog = pair.first;
+    return pair.last;
+  }
+
+  /// Returns a stream that will emit anything the process emits via the
+  /// process's standard error from now on.
+  ///
+  /// This stream will be independent from any other methods that deal with
+  /// standard error, including other calls to [stderrStream].
+  Stream<String> stderrStream() {
+    var pair = tee(_stderrLog);
+    _stderrLog = pair.first;
+    return pair.last;
+  }
+
   /// Writes [line] to the process as stdin.
   void writeLine(String line) {
     schedule(() {
diff --git a/pkg/scheduled_test/lib/src/schedule.dart b/pkg/scheduled_test/lib/src/schedule.dart
index 06064c5..9fecc99 100644
--- a/pkg/scheduled_test/lib/src/schedule.dart
+++ b/pkg/scheduled_test/lib/src/schedule.dart
@@ -503,6 +503,7 @@
 
       var stackString = prefixLines(terseTraceString(trace));
       fullDescription += "\n\nStack trace:\n$stackString";
+      return fullDescription;
     });
     _pendingCallbacks.add(pendingCallback);
 
diff --git a/pkg/scheduled_test/lib/src/utils.dart b/pkg/scheduled_test/lib/src/utils.dart
index 4bd4505..d686ef9 100644
--- a/pkg/scheduled_test/lib/src/utils.dart
+++ b/pkg/scheduled_test/lib/src/utils.dart
@@ -35,7 +35,6 @@
 /// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the
 /// first line is prefixed with that instead.
 String prefixLines(String text, {String prefix: '| ', String firstPrefix}) {
-  if (text == null) return '';
   var lines = text.split('\n');
   if (firstPrefix == null) {
     return lines.map((line) => '$prefix$line').join('\n');
@@ -52,7 +51,11 @@
 /// any code to run, as long as it's not waiting on some external event.
 Future pumpEventQueue([int times=20]) {
   if (times == 0) return new Future.value();
-  return new Future.value().then((_) => pumpEventQueue(times - 1));
+  // We use a delayed future to allow runAsync events to finish. The
+  // Future.value or Future() constructors use runAsync themselves and would
+  // therefore not wait for runAsync callbacks that are scheduled after invoking
+  // this method.
+  return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1));
 }
 
 /// Returns whether [iterable1] has the same elements in the same order as
@@ -130,7 +133,7 @@
   var subscription = stream.listen((value) {
     if (!controller.isClosed) controller.add(value);
   }, onError: (error) {
-    if (!controller.isClosed) controller.signalError(error);
+    if (!controller.isClosed) controller.addError(error);
   }, onDone: controller.close);
   return new Pair<Stream, StreamCanceller>(controllerStream, controller.close);
 }
@@ -146,8 +149,8 @@
     controller1.add(value);
     controller2.add(value);
   }, onError: (error) {
-    controller1.signalError(error);
-    controller2.signalError(error);
+    controller1.addError(error);
+    controller2.addError(error);
   }, onDone: () {
     controller1.close();
     controller2.close();
diff --git a/pkg/scheduled_test/test/substitute_future_test.dart b/pkg/scheduled_test/test/substitute_future_test.dart
index 5cffb4b..b3cade8 100644
--- a/pkg/scheduled_test/test/substitute_future_test.dart
+++ b/pkg/scheduled_test/test/substitute_future_test.dart
@@ -148,9 +148,9 @@
     var completer = new Completer();
     var future = new SubstituteFuture(completer.future);
     completer.complete('success');
-    future.then(expectAsync1((_) {
-      expect(() => future.substitute(new Future.value()),
-          throwsStateError);
-    }));
+    // The completer finishes asynchronously. So we have to wait for it to
+    // be completed before we can substitute.
+    expect(future.then((_) => future.substitute(new Future.value())),
+        throwsStateError);
   });
 }
diff --git a/pkg/scheduled_test/test/value_future_test.dart b/pkg/scheduled_test/test/value_future_test.dart
index 3cf0fb9..3d730cd 100644
--- a/pkg/scheduled_test/test/value_future_test.dart
+++ b/pkg/scheduled_test/test/value_future_test.dart
@@ -98,20 +98,23 @@
     });
 
     test('.value is the result of the future', () {
-      future.then(expectAsync1((_) {
-        expect(future.value, equals(12));
-      }));
+      // The completer calls its listeners asynchronously. We have to wait
+      // before we can access the value of the ValueFuture.
+      expect(future.then((_) => future.value), completion(equals(12)));
     });
 
     test('.hasValue is true', () {
-      future.then(expectAsync1((_) {
-        expect(future.hasValue, isTrue);
-      }));
+      // The completer calls its listeners asynchronously. We have to wait
+      // before we can access the value of the ValueFuture.
+      expect(future.then((_) => future.hasValue), completion(isTrue));
     });
   });
 
   group('after an error completion', () {
     var future;
+    // Since the completer completes asynchronously we need to wait before the
+    // ValueFuture has a value. The safeFuture will execute its callback when
+    // this is the case.
     var safeFuture;
 
     setUp(() {
@@ -122,15 +125,11 @@
     });
 
     test('.value is null', () {
-      safeFuture.then(expectAsync1((_) {
-        expect(future.value, isNull);
-      }));
+      expect(safeFuture.then((_) => future.value), completion(isNull));
     });
 
     test('.hasValue is false', () {
-      safeFuture.then(expectAsync1((_) {
-        expect(future.hasValue, isFalse);
-      }));
+      expect(safeFuture.then((_) => future.hasValue), completion(isFalse));
     });
   });
 }
diff --git a/pkg/serialization/lib/serialization.dart b/pkg/serialization/lib/serialization.dart
index c0ab0d0..5865840 100644
--- a/pkg/serialization/lib/serialization.dart
+++ b/pkg/serialization/lib/serialization.dart
@@ -210,6 +210,7 @@
 import 'dart:async';
 import 'dart:json' as json;
 import 'dart:collection';
+import 'dart:uri';
 
 part 'src/reader_writer.dart';
 part 'src/serialization_rule.dart';
@@ -258,7 +259,8 @@
     // TODO(alanknight): Should this be moved to the format?
     // TODO(alanknight): Allow self-describing in the presence of CustomRule.
     if (_selfDescribing != null) return _selfDescribing;
-    return !rules.any((x) => x is CustomRule);
+    _selfDescribing = !rules.any((x) => x is CustomRule && x is! SymbolRule);
+    return _selfDescribing;
   }
 
   /**
@@ -319,8 +321,7 @@
         List<String> fields,
         List<String> excludeFields}) {
 
-    var rule;
-    rule = new BasicRule(
+    var rule = new BasicRule(
         turnInstanceIntoSomethingWeCanUse(
             instanceOfType),
         constructor, constructorFields, fields, excludeFields);
@@ -464,7 +465,8 @@
           fields: [])
       ..addRule(new NamedObjectRule())
       ..addRule(new MirrorRule())
-      ..addRule(new SymbolRule());
+      ..addRuleFor(new MirrorRule())
+      ..addRuleFor(new SymbolRule());
     meta.namedObjects = namedObjects;
     return meta;
   }
diff --git a/pkg/serialization/lib/src/format.dart b/pkg/serialization/lib/src/format.dart
index e45a7f0..93a345b 100644
--- a/pkg/serialization/lib/src/format.dart
+++ b/pkg/serialization/lib/src/format.dart
@@ -36,26 +36,21 @@
 }
 
 /**
- * A format that stores the data in maps which are converted into a JSON
- * string. Note that the maps aren't nested, and it handles cyclic references
- * by converting object references to [Reference] objects. If you want simple
- * acyclic JSON look at [SimpleJsonFormat].
+ * This is the most basic format, which provides the internal representation
+ * of the serialization, exposing the Reference objects.
  */
-class SimpleMapFormat extends Format {
-
-  const SimpleMapFormat();
+class InternalMapFormat extends Format {
+  const InternalMapFormat();
 
   /**
-   * Generate output for this format from [w] and return it as a String which
-   * is the [json] representation of a nested Map structure. The top level has
+   * Generate output for this format from [w] and return it as a nested Map
+   * structure. The top level has
    * 3 fields, "rules" which may hold a definition of the rules used,
    * "data" which holds the serialized data, and "roots", which holds
    * [Reference] objects indicating the root objects. Note that roots are
-   * necessary because the data is organized in the same way as the object
+   * necessary because the data is not organized in the same way as the object
    * structure, it's a list of lists holding self-contained maps which only
    * refer to other parts via [Reference] objects.
-   * This effectively defines a custom JSON serialization format, although
-   * the details of the format vary depending which rules were used.
    */
   Map<String, dynamic> generateOutput(Writer w) {
     var result = {
@@ -67,7 +62,7 @@
   }
 
   /**
-   * Read a [json] compatible representation of serialized data in this format
+   * Read serialized data written from this format
    * and return the nested Map representation described in [generateOutput]. If
    * the data also includes rule definitions, then these will replace the rules
    * in the [Serialization] for [reader].
@@ -75,6 +70,94 @@
   Map<String, dynamic> read(topLevel, Reader reader) {
     var ruleString = topLevel["rules"];
     reader.readRules(ruleString);
+    reader._data = topLevel["data"];
+    topLevel["roots"] = topLevel["roots"];
+    return topLevel;
+  }
+}
+
+/**
+ * A format that stores the data in maps which can be converted into a JSON
+ * string or passed through an isolate. Note that this consists of maps, but
+ * that they don't follow the original object structure or look like the nested
+ * maps of a [json] representation. They are flat, and [Reference] objects
+ * are converted into a map form that will not make sense to
+ * anything but this format. For simple acyclic JSON that other programs
+ * can read, use [SimpleJsonFormat]. This is the default format, and is
+ * easier to read than the more efficient [SimpleFlatFormat].
+ */
+class SimpleMapFormat extends InternalMapFormat {
+
+  const SimpleMapFormat();
+
+  /**
+   * Generate output for this format from [w] and return it as a String which
+   * is the [json] representation of a nested Map structure. The top level has
+   * 3 fields, "rules" which may hold a definition of the rules used,
+   * "data" which holds the serialized data, and "roots", which holds
+   * [Reference] objects indicating the root objects. Note that roots are
+   * necessary because the data is not organized in the same way as the object
+   * structure, it's a list of lists holding self-contained maps which only
+   * refer to other parts via [Reference] objects.
+   * This effectively defines a custom JSON serialization format, although
+   * the details of the format vary depending which rules were used.
+   */
+  Map<String, dynamic> generateOutput(Writer w) {
+    forAllStates(w, (x) => x is Reference, referenceToMap);
+    var result = super.generateOutput(w);
+    result["roots"] = result["roots"].map(
+        (x) => x is Reference ? referenceToMap(x) : x).toList();
+    return result;
+  }
+
+  /**
+   * Convert the data generated by the rules to have maps with the fields
+   * of [Reference] objects instead of the [Reference] so that the structure
+   * can be serialized between isolates and json easily.
+   */
+  forAllStates(ReaderOrWriter w, bool predicate(value),
+               void transform(value)) {
+    for (var eachRule in w.rules) {
+      var ruleData = w.states[eachRule.number];
+      for (var data in ruleData) {
+        keysAndValues(data).forEach((key, value) {
+          if (predicate(value)) {
+            data[key] = transform(value);
+          }
+        });
+      }
+    }
+  }
+
+  /** Convert the reference to a [json] serializable form. */
+  Map<String, int> referenceToMap(Reference ref) => ref == null ? null :
+    {
+      "__Ref" : 0,
+      "rule" : ref.ruleNumber,
+      "object" : ref.objectNumber
+    };
+
+  /**
+   * Convert the [referenceToMap] form for a reference back to a [Reference]
+   * object.
+   */
+  Reference mapToReference(ReaderOrWriter parent, Map<String, int> ref) =>
+      ref == null ? null : new Reference(parent, ref["rule"], ref["object"]);
+
+  /**
+   * Read serialized data written in this format
+   * and return the nested Map representation described in [generateOutput]. If
+   * the data also includes rule definitions, then these will replace the rules
+   * in the [Serialization] for [reader].
+   */
+  Map<String, dynamic> read(topLevel, Reader reader) {
+    super.read(topLevel, reader);
+    forAllStates(reader,
+        (ref) => ref is Map && ref["__Ref"] != null,
+        (ref) => mapToReference(reader, ref));
+    topLevel["roots"] = topLevel["roots"]
+        .map((x) => x is Map<String, int> ? mapToReference(reader, x) : x)
+        .toList();
     return topLevel;
   }
 }
@@ -90,7 +173,7 @@
  * If the [storeRoundTripInfo] field of the format is set to true, then this
  * will store the rule number along with the data, allowing reconstruction.
  */
-class SimpleJsonFormat extends Format {
+class SimpleJsonFormat extends SimpleMapFormat {
 
   /**
    * Indicate if we should store rule numbers with map/list data so that we
diff --git a/pkg/serialization/lib/src/reader_writer.dart b/pkg/serialization/lib/src/reader_writer.dart
index 38ff10a..b40196e 100644
--- a/pkg/serialization/lib/src/reader_writer.dart
+++ b/pkg/serialization/lib/src/reader_writer.dart
@@ -241,6 +241,9 @@
   /** Return the list of serialization rules we are using.*/
   List<SerializationRule> get rules;
 
+  /** Return the internal collection of object state and [Reference] objects. */
+  List<List> get states;
+
   /**
    * Return the object, or state, that ref points to, depending on which
    * we're generating.
@@ -278,6 +281,9 @@
    */
   List<List> _data;
 
+  /** Return the internal collection of object state and [Reference] objects. */
+  get states => _data;
+
   /**
    * The resulting objects, indexed according to the same scheme as
    * _data, where each rule has a number, and rules keep track of the objects
@@ -467,7 +473,7 @@
   asReference(anObject, {Function ifReference: doNothing,
       Function ifNotReference : doNothing}) {
     if (anObject is Reference) return ifReference(anObject);
-    if (anObject is Map && anObject["__Ref"] == true) {
+    if (anObject is Map && anObject["__Ref"] != null) {
       var ref =
           new Reference(this, anObject["rule"], anObject["object"]);
       return ifReference(ref);
@@ -509,12 +515,12 @@
 
   Trace(this.writer);
 
-  addRoot(object) {
+  void addRoot(object) {
     roots.add(object);
   }
 
   /** A convenience method to add a single root and trace it in one step. */
-  trace(object) {
+  void trace(object) {
     addRoot(object);
     traceAll();
   }
@@ -523,7 +529,7 @@
    * Process all of the objects reachable from our roots via state that the
    * serialization rules access.
    */
-  traceAll() {
+  void traceAll() {
     queue.addAll(roots);
     while (!queue.isEmpty) {
       var next = queue.removeFirst();
@@ -585,8 +591,8 @@
    */
   // TODO(alanknight): This is a hack both in defining a toJson specific to a
   // particular representation, and the use of a bogus sentinel "__Ref"
-  Map<String, dynamic> toJson() => {
-    "__Ref" : true,
+  Map<String, int> toJson() => {
+    "__Ref" : 0,
     "rule" : ruleNumber,
     "object" : objectNumber
   };
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index 1a592a7..53c0f72 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -138,7 +138,7 @@
  */
 class ListRule extends SerializationRule {
 
-  appliesTo(object, Writer w) => object is List;
+  bool appliesTo(object, Writer w) => object is List;
 
   bool get storesStateAsLists => true;
 
@@ -196,7 +196,7 @@
  */
 class MapRule extends SerializationRule {
 
-  appliesTo(object, Writer w) => object is Map;
+  bool appliesTo(object, Writer w) => object is Map;
 
   bool get storesStateAsMaps => true;
 
@@ -272,9 +272,7 @@
  * num, String, and bool.
  */
 class PrimitiveRule extends SerializationRule {
-  appliesTo(object, Writer w) {
-    return isPrimitive(object);
-  }
+  bool appliesTo(object, Writer w) => isPrimitive(object);
   extractState(object, Function f, Writer w) => object;
   flatten(object, Writer writer) {}
   inflateEssential(state, Reader r) => state;
@@ -334,7 +332,7 @@
 
   create(state) => construct(state);
 
-  setState(object, state) {
+  void setState(object, state) {
     if (setNonEssentialState == null) return;
     setNonEssentialState(object, state);
   }
@@ -379,7 +377,7 @@
   inflateNonEssential(state, object, Reader r) {}
 
   /** Return the name for this object in the Writer. */
-  nameFor(object, Writer writer) => writer.nameFor(object);
+  String nameFor(object, Writer writer) => writer.nameFor(object);
 }
 
 /**
@@ -392,7 +390,8 @@
  */
 class MirrorRule extends NamedObjectRule {
   bool appliesTo(object, Writer writer) => object is DeclarationMirror;
-  nameFor(DeclarationMirror object, Writer writer) =>
+
+  String nameFor(DeclarationMirror object, Writer writer) =>
       MirrorSystem.getName(object.qualifiedName);
 
   inflateEssential(state, Reader r) {
@@ -400,12 +399,25 @@
     var lookupFull = r.objectNamed(qualifiedName, (x) => null);
     if (lookupFull != null) return lookupFull;
     var separatorIndex = qualifiedName.lastIndexOf(".");
-    var lib = new Symbol(qualifiedName.substring(0, separatorIndex));
     var type = qualifiedName.substring(separatorIndex + 1);
     var lookup = r.objectNamed(type, (x) => null);
     if (lookup != null) return lookup;
-    var libMirror = currentMirrorSystem().findLibrary(lib).first;
-    return libMirror.classes[new Symbol(type)];
+    var name = qualifiedName.substring(0, separatorIndex);
+    // This is very ugly. The library name for an unnamed library is its URI.
+    // That can't be constructed as a Symbol, so we can't use findLibrary.
+    // So follow one or the other path depending if it has a colon, which we
+    // assume is in any URI and can't be in a Symbol.
+    if (name.contains(":")) {
+      var uri = new Uri(name);
+      var libMirror = currentMirrorSystem().libraries[uri];
+      return libMirror.classes[new Symbol(type)];
+    } else {
+      var symbol = new Symbol(name);
+      var typeSymbol = new Symbol(type);
+      var libMirror = currentMirrorSystem().findLibrary(symbol).firstWhere(
+        (lib) => lib.classes[typeSymbol] != null);
+      return libMirror.classes[typeSymbol];
+    }
   }
 }
 
@@ -467,7 +479,7 @@
   // We don't want to have to make the end user tell us how long the list is
   // separately, so write it out for each object, even though they're all
   // expected to be the same length.
-  get hasVariableLengthEntries => true;
+  bool get hasVariableLengthEntries => true;
 }
 
 /** A hard-coded rule for serializing Symbols. */
@@ -475,7 +487,7 @@
   bool appliesTo(instance, _) => instance is Symbol;
   getState(instance) => [MirrorSystem.getName(instance)];
   create(state) => new Symbol(state[0]);
-  setState(symbol, state) {}
+  void setState(symbol, state) {}
   int get dataLength => 1;
   bool get hasVariableLengthEntries => false;
 }
diff --git a/pkg/serialization/test/serialization_test.dart b/pkg/serialization/test/serialization_test.dart
index db5b5f1..eeca085 100644
--- a/pkg/serialization/test/serialization_test.dart
+++ b/pkg/serialization/test/serialization_test.dart
@@ -9,6 +9,7 @@
 import 'package:serialization/serialization.dart';
 import 'package:serialization/src/serialization_helpers.dart';
 import 'package:serialization/src/mirrors_helpers.dart';
+import 'dart:isolate';
 
 part 'test_models.dart';
 
@@ -18,7 +19,8 @@
   a1.street = 'N 34th';
   a1.city = 'Seattle';
 
-  var formats = [const SimpleFlatFormat(), const SimpleMapFormat(),
+  var formats = [const InternalMapFormat(),
+                 const SimpleFlatFormat(), const SimpleMapFormat(),
                  const SimpleJsonFormat(storeRoundTripInfo: true)];
 
   test('Basic extraction of a simple object', () {
@@ -46,7 +48,7 @@
         ..addRuleFor(a1).configureForMaps();
     // TODO(alanknight): Need a better API for getting to flat state without
     // actually writing.
-    var w = new Writer(s);
+    var w = new Writer(s, const InternalMapFormat());
     w.write(p1);
     var personRule = s.rules.firstWhere(
         (x) => x is BasicRule && x.type == reflect(p1).type);
@@ -215,7 +217,7 @@
 
   test('Flatten references in a cyclical structure', () {
     var s = new Serialization();
-    var w = new Writer(s);
+    var w = new Writer(s, const InternalMapFormat());
     w.trace = new Trace(w);
     w.write(n1);
     expect(w.states.length, 6); // prims, lists, essential lists, basic, symbol
@@ -235,6 +237,25 @@
     runRoundTripTest(nodeSerializerReflective);
   });
 
+  test('round-trip with explicit self-description', () {
+    // We provide a setup function which, when run the second time,
+    // returns a blank serialization, to make sure it will fail
+    // the second time.
+    var s;
+    oneShotSetup(node) {
+      if (s == null) {
+        s = nodeSerializerReflective(node)..selfDescribing = true;
+        return s;
+      } else {
+        s = null;
+        return new Serialization.blank()
+            ..namedObjects['Node'] = reflect(new Node('')).type;;
+      }
+    }
+
+    runRoundTripTest(oneShotSetup);
+  });
+
   test('round-trip ClosureRule', () {
     runRoundTripTest(nodeSerializerNonReflective);
   });
@@ -508,13 +529,13 @@
     var s = new Serialization()..addRuleFor(new Person());
     var data = {"abc" : 1, "def" : "ghi"};
     data["person"] = new Person()..name = "Foo";
-    var output = s.write(data, const SimpleMapFormat());
+    var output = s.write(data, const InternalMapFormat());
     var mapRule = s.rules.firstWhere((x) => x is MapRule);
     var map = output["data"][mapRule.number][0];
     expect(map is Map, isTrue);
     expect(map["abc"], 1);
     expect(map["def"], "ghi");
-    expect(new Reader(s).asReference(map["person"]) is Reference, isTrue);
+    expect(map["person"] is Reference, isTrue);
   });
 
   test("MirrorRule with lookup by qualified name rather than named object", () {
@@ -526,6 +547,35 @@
     expect(MirrorSystem.getName(input.simpleName), "Address");
   });
 
+  test('round-trip, default format, pass to isolate', () {
+      Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
+      n1.children = [n2, n3];
+      n2.parent = n1;
+      n3.parent = n1;
+      var s = nodeSerializerReflective(n1);
+      var output = s.write(n2);
+      var port = spawnFunction(echo);
+      port.call(output).then(expectAsync1((input) => verify(input)));
+  });
+}
+
+/**
+ * Verify serialized output that we have passed to an isolate and back.
+ */
+verify(input) {
+  var s2 = nodeSerializerReflective(new Node("a"));
+  var reader = new Reader(s2);
+  var m2 = reader.read(input);
+  var m1 = m2.parent;
+  expect(m1 is Node, isTrue);
+  var children = m1.children;
+  expect(m1.name,"1");
+  var m3 = m1.children.last;
+  expect(m2.name, "2");
+  expect(m3.name, "3");
+  expect(m2.parent, m1);
+  expect(m3.parent, m1);
+  expect(m1.parent, isNull);
 }
 
 /******************************************************************************
@@ -729,7 +779,7 @@
   bool appliesTo(instance, _) => instance.runtimeType == Node;
   getState(instance) => [instance.parent, instance.name, instance.children];
   create(state) => new Node(state[1]);
-  setState(Node node, state) {
+  void setState(Node node, state) {
     node.parent = state[0];
     node.children = state[2];
   }
@@ -749,7 +799,7 @@
       ..[instance.address] = "address";
   }
   create(state) => new Person();
-  setState(Person a, state) {
+  void setState(Person a, state) {
     a.name = findValue("name", state);
     a.address = findValue("address", state);
   }
@@ -762,3 +812,13 @@
     return null;
   }
 }
+
+/**
+ * Function used in an isolate to make sure that the output passes through
+ * isolate serialization properly.
+ */
+echo() {
+  port.receive((msg, reply) {
+    reply.send(msg);
+  });
+}
diff --git a/pkg/unittest/lib/test_controller.js b/pkg/unittest/lib/test_controller.js
index 34d56ed..c032854 100644
--- a/pkg/unittest/lib/test_controller.js
+++ b/pkg/unittest/lib/test_controller.js
@@ -33,10 +33,17 @@
 
 var waitForDone = false;
 
+function sendDomToTestDriver() {
+  if (window.opener) {
+    window.opener.postMessage(window.document.body.innerHTML, "*");
+  }
+}
+
 function processMessage(msg) {
   if (typeof msg != 'string') return;
   if (msg == 'unittest-suite-done') {
     if (testRunner) testRunner.notifyDone();
+    sendDomToTestDriver();
   } else if (msg == 'unittest-suite-wait-for-done') {
     waitForDone = true;
     if (testRunner) testRunner.startedDartTest = true;
@@ -49,6 +56,7 @@
   } else if (msg == 'unittest-suite-success') {
     dartPrint('PASS');
     if (testRunner) testRunner.notifyDone();
+    sendDomToTestDriver();
   } else if (msg == 'unittest-suite-fail') {
     showErrorAndExit('Some tests failed.');
   }
@@ -72,6 +80,7 @@
   // FAIL and will continue polling until one of these words show up.
   dartPrint('FAIL');
   if (testRunner) testRunner.notifyDone();
+  sendDomToTestDriver();
 }
 
 function onLoad(e) {
@@ -107,6 +116,7 @@
     setTimeout(function() {
       if (testRunner && !testRunner.startedDartTest) {
         testRunner.notifyDone();
+        sendDomToTestDriver();
       }
     }, 0);
   }, 50);
diff --git a/pkg/unittest/lib/unittest.dart b/pkg/unittest/lib/unittest.dart
index 479e392..7dd1e1a 100644
--- a/pkg/unittest/lib/unittest.dart
+++ b/pkg/unittest/lib/unittest.dart
@@ -28,10 +28,10 @@
  *  * __Checks__: Test expectations can be specified via [expect]
  *  * __Matchers__: [expect] assertions are written declaratively using the
  *    [Matcher] class.
- *  * __Configuration__: The framework can be adapted by calling [configure] with a
- *    [Configuration]. See the other libraries in the `unittest` package for
- *    alternative implementations of [Configuration] including
- *    `compact_vm_config.dart`, `html_config.dart` and
+ *  * __Configuration__: The framework can be adapted by setting
+ *    [unittestConfiguration] with a [Configuration]. See the other libraries
+ *    in the `unittest` package for alternative implementations of
+ *    [Configuration] including `compact_vm_config.dart`, `html_config.dart` and
  *    `html_enhanced_config.dart`.
  *
  * ##Examples##
@@ -179,7 +179,7 @@
 Configuration _config;
 
 /**
- * [Configuration] used by the unittest library. Note that if a 
+ * [Configuration] used by the unittest library. Note that if a
  * configuration has not been set, calling this getter will create
  * a default configuration.
  */
@@ -865,7 +865,7 @@
 
 // Stack formatting utility. Strips extraneous content from a stack trace.
 // Stack frame lines are parsed with a regexp, which has been tested
-// in Chrome, Firefox and the VM. If a line fails to be parsed it is 
+// in Chrome, Firefox and the VM. If a line fails to be parsed it is
 // included in the output to be conservative.
 //
 // The output stack consists of everything after the call to TestCase._run.
@@ -894,8 +894,8 @@
   } else {
     return stack.toString();
   }
- 
-  // Calculate the max width of first column so we can 
+
+  // Calculate the max width of first column so we can
   // pad to align the second columns.
   int padding = lines.fold(0, (n, line) {
     var match = _frameRegExp.firstMatch(line);
diff --git a/pkg/unittest/lib/vm_config.dart b/pkg/unittest/lib/vm_config.dart
index d8b3f23..7ff2154 100644
--- a/pkg/unittest/lib/vm_config.dart
+++ b/pkg/unittest/lib/vm_config.dart
@@ -7,6 +7,7 @@
  */
 library unittest_vm_config;
 
+import 'dart:async';
 import 'dart:io';
 import 'unittest.dart';
 
@@ -38,14 +39,18 @@
   }
 
   void onDone(bool success) {
+    int status;
     try {
       super.onDone(success);
-      exit(0);
+      status = 0;
     } catch (ex) {
       // A non-zero exit code is used by the test infrastructure to detect
       // failure.
-      exit(1);
+      status = 1;
     }
+    Future.wait([stdout.close(), stderr.close()]).then((_) {
+      exit(status);
+    });
   }
 }
 
diff --git a/pkg/unittest/test/unittest_test.dart b/pkg/unittest/test/unittest_test.dart
index f1d1aad..1bbfb18 100644
--- a/pkg/unittest/test/unittest_test.dart
+++ b/pkg/unittest/test/unittest_test.dart
@@ -251,10 +251,10 @@
       });
       test('foo5', () {
       });
-    } else if (testName == 'test returning future using Timer') {
+    } else if (testName == 'test returning future using runAsync') {
       test("successful", () {
         return _defer(() {
-          Timer.run(() {
+          runAsync(() {
             guardAsync(() {
               expect(true, true);
             });
@@ -264,7 +264,7 @@
       test("fail1", () {
         var callback = expectAsync0((){});
         return _defer(() {
-          Timer.run(() {
+          runAsync(() {
             guardAsync(() {
               expect(true, false);
               callback();
@@ -276,7 +276,7 @@
         var callback = expectAsync0((){});
         var excesscallback = expectAsync0((){});
         return _defer(() {
-          Timer.run(() {
+          runAsync(() {
             guardAsync(() {
               excesscallback();
               excesscallback();
@@ -288,7 +288,7 @@
       test("fail2", () {
         var callback = expectAsync0((){});
         return _defer(() {
-          Timer.run(() {
+          runAsync(() {
             guardAsync(() {
               fail('failure');
               callback();
@@ -300,7 +300,7 @@
         var callback = expectAsync0((){});
         var excesscallback = expectAsync0((){});
         return _defer(() {
-          Timer.run(() {
+          runAsync(() {
             guardAsync(() {
               excesscallback();
               excesscallback();
@@ -444,7 +444,7 @@
         'error2:Callback called more times than expected (1).:'
         'fail2:failure:'
         'foo5'),
-    'test returning future using Timer': buildStatusString(2, 4, 0,
+    'test returning future using runAsync': buildStatusString(2, 4, 0,
         'successful::'
         'fail1:Expected: <false> but: was <true>.:'
         'error1:Callback called more times than expected (1).:'
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index fcfb1ee..9a6bafe 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -44,6 +44,7 @@
   V(File_Truncate, 2)                                                          \
   V(File_Length, 1)                                                            \
   V(File_LengthFromPath, 1)                                                    \
+  V(File_Stat, 1)                                                              \
   V(File_LastModified, 1)                                                      \
   V(File_Flush, 1)                                                             \
   V(File_Create, 1)                                                            \
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 0b5e016..e113927 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -783,11 +783,6 @@
 }
 
 
-static int kArgumentError = 1;
-static int kOSError = 2;
-static int kFileClosedError = 3;
-
-
 CObject* CObject::IllegalArgumentError() {
   CObjectArray* result = new CObjectArray(CObject::NewArray(1));
   result->SetAt(0, new CObjectInt32(CObject::NewInt32(kArgumentError)));
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index a9b86f7..437570d 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -207,6 +207,12 @@
 
 class CObject {
  public:
+  // These match the constants in sdk/lib/io/common.dart.
+  static const int kSuccess = 0;
+  static const int kArgumentError = 1;
+  static const int kOSError = 2;
+  static const int kFileClosedError = 3;
+
   explicit CObject(Dart_CObject *cobject) : cobject_(cobject) {}
   Dart_CObject::Type type() { return cobject_->type; }
   Dart_CObject::TypedDataType byte_array_type() {
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index bc8ca4c..b885f54 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -582,6 +582,38 @@
 }
 
 
+void FUNCTION_NAME(File_Stat)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  if (Dart_IsString(Dart_GetNativeArgument(args, 0))) {
+    const char* path =
+        DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
+
+    int64_t stat_data[File::kStatSize];
+    File::Stat(path, stat_data);
+    Dart_Handle returned_data = Dart_NewTypedData(kInt64, File::kStatSize);
+    if (Dart_IsError(returned_data)) Dart_PropagateError(returned_data);
+    Dart_TypedData_Type data_type_unused;
+    void* data_location;
+    intptr_t data_length_unused;
+    Dart_Handle status = Dart_TypedDataAcquireData(returned_data,
+                                                   &data_type_unused,
+                                                   &data_location,
+                                                   &data_length_unused);
+    if (Dart_IsError(status)) Dart_PropagateError(status);
+    memmove(data_location, stat_data, File::kStatSize * sizeof(int64_t));
+    status = Dart_TypedDataReleaseData(returned_data);
+    if (Dart_IsError(status)) Dart_PropagateError(status);
+    Dart_SetReturnValue(args, returned_data);
+  } else {
+    Dart_Handle err = DartUtils::NewDartArgumentError(
+        "Non-string argument to FileSystemEntity.stat");
+    if (Dart_IsError(err)) Dart_PropagateError(err);
+    Dart_SetReturnValue(args, err);
+  }
+  Dart_ExitScope();
+}
+
+
 void FUNCTION_NAME(File_AreIdentical)(Dart_NativeArguments args) {
   Dart_EnterScope();
   if (Dart_IsString(Dart_GetNativeArgument(args, 0)) &&
@@ -1122,6 +1154,26 @@
 }
 
 
+static CObject* FileStatRequest(const CObjectArray& request) {
+  if (request.Length() == 2 &&
+      request[1]->IsString()) {
+    int64_t data[File::kStatSize];
+    CObjectString path(request[1]);
+    File::Stat(path.CString(), data);
+    CObjectArray* result =
+        new CObjectArray(CObject::NewArray(File::kStatSize));
+    for (int i = 0; i < File::kStatSize; ++i) {
+      result->SetAt(i, new CObjectInt64(CObject::NewInt64(data[i])));
+    }
+    CObjectArray* wrapper = new CObjectArray(CObject::NewArray(2));
+    wrapper->SetAt(0, new CObjectInt32(CObject::NewInt32(CObject::kSuccess)));
+    wrapper->SetAt(1, result);
+    return wrapper;
+  }
+  return CObject::IllegalArgumentError();
+}
+
+
 static void FileService(Dart_Port dest_port_id,
                  Dart_Port reply_port_id,
                  Dart_CObject* message) {
@@ -1203,6 +1255,9 @@
         case File::kIdenticalRequest:
           response = FileIdenticalRequest(request);
           break;
+        case File::kStatRequest:
+          response = FileStatRequest(request);
+          break;
         default:
           UNREACHABLE();
       }
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index cf9f689..cfc48c1 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -85,7 +85,19 @@
     kDeleteLinkRequest = 20,
     kLinkTargetRequest = 21,
     kTypeRequest = 22,
-    kIdenticalRequest = 23
+    kIdenticalRequest = 23,
+    kStatRequest = 24
+  };
+
+  enum FileStat {
+    // These match the constants in FileStat in file_system_entity.dart.
+    kType = 0,
+    kCreatedTime = 1,
+    kModifiedTime = 2,
+    kAccessedTime = 3,
+    kMode = 4,
+    kSize = 5,
+    kStatSize = 6
   };
 
   ~File();
@@ -142,6 +154,7 @@
   static bool Delete(const char* path);
   static bool DeleteLink(const char* path);
   static off_t LengthFromPath(const char* path);
+  static void Stat(const char* path, int64_t* data);
   static time_t LastModified(const char* path);
   static char* LinkTarget(const char* pathname);
   static bool IsAbsolutePath(const char* path);
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 9bb5e1a..e8a1fa9 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -201,6 +201,34 @@
 }
 
 
+void File::Stat(const char* name, int64_t* data) {
+  struct stat st;
+  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+    if (S_ISREG(st.st_mode)) {
+      data[kType] = kIsFile;
+    } else if (S_ISDIR(st.st_mode)) {
+      data[kType] = kIsDirectory;
+    } else if (S_ISLNK(st.st_mode)) {
+      data[kType] = kIsLink;
+    } else {
+      data[kType] = kDoesNotExist;
+    }
+    data[kCreatedTime] = st.st_ctime;
+    data[kModifiedTime] = st.st_mtime;
+    data[kAccessedTime] = st.st_atime;
+    data[kMode] = st.st_mode;
+    data[kSize] = st.st_size;
+  } else {
+    data[kType] = kDoesNotExist;
+    data[kCreatedTime] = 0;
+    data[kModifiedTime] = 0;
+    data[kAccessedTime] = 0;
+    data[kMode] = 0;
+    data[kSize] = 0;
+  }
+}
+
+
 time_t File::LastModified(const char* name) {
   struct stat st;
   if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 26c047d..7c4ddda 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -202,6 +202,34 @@
 }
 
 
+void File::Stat(const char* name, int64_t* data) {
+  struct stat st;
+  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+    if (S_ISREG(st.st_mode)) {
+      data[kType] = kIsFile;
+    } else if (S_ISDIR(st.st_mode)) {
+      data[kType] = kIsDirectory;
+    } else if (S_ISLNK(st.st_mode)) {
+      data[kType] = kIsLink;
+    } else {
+      data[kType] = kDoesNotExist;
+    }
+    data[kCreatedTime] = st.st_ctime;
+    data[kModifiedTime] = st.st_mtime;
+    data[kAccessedTime] = st.st_atime;
+    data[kMode] = st.st_mode;
+    data[kSize] = st.st_size;
+  } else {
+    data[kType] = kDoesNotExist;
+    data[kCreatedTime] = 0;
+    data[kModifiedTime] = 0;
+    data[kAccessedTime] = 0;
+    data[kMode] = 0;
+    data[kSize] = 0;
+  }
+}
+
+
 time_t File::LastModified(const char* name) {
   struct stat st;
   if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 0b99153..c693f94 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -204,6 +204,34 @@
 }
 
 
+void File::Stat(const char* name, int64_t* data) {
+  struct stat st;
+  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+    if (S_ISREG(st.st_mode)) {
+      data[kType] = kIsFile;
+    } else if (S_ISDIR(st.st_mode)) {
+      data[kType] = kIsDirectory;
+    } else if (S_ISLNK(st.st_mode)) {
+      data[kType] = kIsLink;
+    } else {
+      data[kType] = kDoesNotExist;
+    }
+    data[kCreatedTime] = st.st_ctime;
+    data[kModifiedTime] = st.st_mtime;
+    data[kAccessedTime] = st.st_atime;
+    data[kMode] = st.st_mode;
+    data[kSize] = st.st_size;
+  } else {
+    data[kType] = kDoesNotExist;
+    data[kCreatedTime] = 0;
+    data[kModifiedTime] = 0;
+    data[kAccessedTime] = 0;
+    data[kMode] = 0;
+    data[kSize] = 0;
+  }
+}
+
+
 time_t File::LastModified(const char* name) {
   struct stat st;
   if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
diff --git a/runtime/bin/file_system_entity_patch.dart b/runtime/bin/file_system_entity_patch.dart
index 13a7dc8..2c2b324 100644
--- a/runtime/bin/file_system_entity_patch.dart
+++ b/runtime/bin/file_system_entity_patch.dart
@@ -2,6 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+patch class FileStat {
+  /* patch */ static List<int> _statSync(String path) native "File_Stat";
+}
+
+
 patch class FileSystemEntity {
   /* patch */ static _getType(String path, bool followLinks)
       native "File_GetType";
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 4341edc..3162003 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -391,6 +391,31 @@
 }
 
 
+void File::Stat(const char* name, int64_t* data) {
+  File::Type type = GetType(name, false);
+  data[kType] = type;
+  data[kCreatedTime] = 0;
+  data[kModifiedTime] = 0;
+  data[kAccessedTime] = 0;
+  data[kMode] = 0;
+  data[kSize] = 0;
+  if (type != kDoesNotExist) {
+    struct _stat64 st;
+    const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+    int stat_status = _wstat64(system_name, &st);
+    if (stat_status == 0) {
+      data[kCreatedTime] = st.st_ctime;
+      data[kModifiedTime] = st.st_mtime;
+      data[kAccessedTime] = st.st_atime;
+      data[kMode] = st.st_mode;
+      data[kSize] = st.st_size;
+    } else {
+      data[kType] = File::kDoesNotExist;
+    }
+  }
+}
+
+
 time_t File::LastModified(const char* name) {
   struct _stat st;
   const wchar_t* system_name = StringUtils::Utf8ToWide(name);
diff --git a/runtime/embedders/openglui/common/vm_glue.cc b/runtime/embedders/openglui/common/vm_glue.cc
index 4cb5ff8..91a26db 100644
--- a/runtime/embedders/openglui/common/vm_glue.cc
+++ b/runtime/embedders/openglui/common/vm_glue.cc
@@ -129,6 +129,37 @@
   // "--trace_compiler",
 };
 
+static void* openFileCallback(const char* name, bool write) {
+  return fopen(name, write ? "w" : "r");
+}
+
+static void readFileCallback(const uint8_t** data, intptr_t* fileLength,
+    void* stream) {
+  if (!stream) {
+    *data = 0;
+    *fileLength = 0;
+  } else {
+    FILE* file = reinterpret_cast<FILE*>(stream);
+
+    // Get the file size.
+    fseek(file, 0, SEEK_END);
+    *fileLength = ftell(file);
+    rewind(file);
+
+    // Allocate data buffer.
+    *data = new uint8_t[*fileLength];
+    *fileLength = fread(const_cast<uint8_t*>(*data), 1, *fileLength, file);
+  }
+}
+
+static void writeFileCallback(const void* data, intptr_t length, void* file) {
+  fwrite(data, 1, length, reinterpret_cast<FILE*>(file));
+}
+
+static void closeFileCallback(void* file) {
+  fclose(reinterpret_cast<FILE*>(file));
+}
+
 int VMGlue::InitializeVM() {
   // We need the next call to get Dart_Initialize not to bail early.
   LOGI("Setting VM Options");
@@ -138,13 +169,13 @@
   // creating and shutting down isolates.
   LOGI("Initializing Dart");
   if (!Dart_Initialize(CreateIsolateAndSetup,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL)) {
+                       0,
+                       0,
+                       0,
+                       openFileCallback,
+                       readFileCallback,
+                       writeFileCallback,
+                       closeFileCallback)) {
     LOGE("VM initialization failed\n");
     return -1;
   }
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index d72c662..bbaed07 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1810,7 +1810,7 @@
  * \return Success if the internal data address is released successfully.
  *   Otherwise, returns an error handle.
  */
-DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle array);
+DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object);
 
 
 // --- Closures ---
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index bb68f0b..b26f098 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -5,6 +5,7 @@
 
 // TODO(srdjan): Use shared array implementation.
 class _ObjectArray<E> implements List<E> {
+  static final int _classId = (new _ObjectArray(0))._cid;
 
   factory _ObjectArray(length) native "ObjectArray_allocate";
 
@@ -275,6 +276,7 @@
 // implementation (checks when modifying). We should keep watching
 // the inline cache misses.
 class _ImmutableArray<E> implements List<E> {
+  static final int _classId = (const [])._cid;
 
   factory _ImmutableArray._uninstantiable() {
     throw new UnsupportedError(
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index f65380b..1e69b65 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -3,10 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 class _GrowableObjectArray<T> implements List<T> {
-  factory _GrowableObjectArray._uninstantiable() {
-    throw new UnsupportedError(
-        "GrowableObjectArray can only be allocated by the VM");
-  }
+  static final int _classId = (new _GrowableObjectArray(0))._cid;
 
   void insert(int index, T element) {
     if (index < 0 || index > length) {
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 55d3626..e57976b 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -164,12 +164,17 @@
   double toDouble() { return new _Double.fromInteger(this); }
 
   int pow(int exponent) {
-    double res = this.toDouble().pow(exponent);
-    if (res.isInfinite) {
-      // Use Bigint instead.
-      throw "_IntegerImplementation.pow not implemented for large integers.";
+    // Exponentiation by squaring.
+    int base = this;
+    int result = 1;
+    while (exponent != 0) {
+      if ((exponent & 1) == 1) {
+        result *= base;
+      }
+      exponent >>= 1;
+      base *= base;
     }
-    return res.toInt();
+    return result;
   }
 
   String toStringAsFixed(int fractionDigits) {
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 5682bec..a0c7711 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -5,8 +5,11 @@
 import "dart:typed_data";
 
 // A VM patch of the dart:math library.
+
+// If [x] is an [int] and [exponent] is a non-negative [int], the result is
+// an [int], otherwise the result is a [double].
 patch num pow(num x, num exponent) {
-  if (exponent is int) {
+  if ((x is int) && (exponent is int) && (exponent >= 0)) {
     return x.pow(exponent);
   }
   // Double.pow will call exponent.toDouble().
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index bebc1c6..ac26d087 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -15,6 +15,13 @@
 DECLARE_FLAG(bool, enable_type_checks);
 
 
+DEFINE_NATIVE_ENTRY(Object_cid, 1) {
+  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(instance.clazz());
+  return Smi::New(cls.id());
+}
+
+
 DEFINE_NATIVE_ENTRY(Object_toString, 1) {
   const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
   const char* c_str = instance.ToCString();
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index fba43fb..72b158a 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -62,4 +62,6 @@
     });
     return result;
   }
+
+  int get _cid native "Object_cid";
 }
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 214e1f0..e9f5759 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -29,16 +29,17 @@
   static String createFromCharCodes(Iterable<int> charCodes) {
     if (charCodes != null) {
       // TODO(srdjan): Also skip copying of typed arrays.
-      if (charCodes is! _ObjectArray &&
-          charCodes is! _GrowableObjectArray &&
-          charCodes is! _ImmutableArray) {
+      final ccid = charCodes._cid;
+      if ((ccid != _ObjectArray._classId) &&
+          (ccid != _GrowableObjectArray._classId) &&
+          (ccid != _ImmutableArray._classId)) {
         charCodes = new List<int>.from(charCodes, growable: false);
       }
 
       bool isOneByteString = true;
       for (int i = 0; i < charCodes.length; i++) {
         int e = charCodes[i];
-        if (e is! int) throw new ArgumentError(e);
+        if (e is! _Smi) throw new ArgumentError(e);
         // Is e Latin1?
         if ((e < 0) || (e > 0xFF)) {
           isOneByteString = false;
@@ -342,7 +343,7 @@
     int totalLength = 0;
     for (int i = 0; i < numValues; i++) {
       var s = values[i].toString();
-      if (isOneByteString && (s is _OneByteString)) {
+      if (isOneByteString && (s._cid == _OneByteString._classId)) {
         totalLength += s.length;
       } else {
         isOneByteString = false;
@@ -448,11 +449,11 @@
     final len = strings.length;
     bool isOneByteString = true;
     int totalLength = 0;
-    if (strings is _ObjectArray) {
+    if (strings._cid == _ObjectArray._clCId) {
       stringsArray = strings;
       for (int i = 0; i < len; i++) {
         var string = strings[i];
-        if (string is _OneByteString) {
+        if (string._cid == _OneByteString._classId) {
           totalLength += string.length;
         } else {
           isOneByteString = false;
@@ -465,7 +466,7 @@
       int i = 0;
       for (int i = 0; i < len; i++) {
         var string = strings[i];
-        if (string is _OneByteString) {
+        if (string._cid == _OneByteString.clCid) {
           totalLength += s.length;
         } else {
           isOneByteString = false;
@@ -485,7 +486,7 @@
     final stringsLength = strings.length;
     for (int i = 0; i < stringsLength; i++) {
       var e = strings[i];
-      if (e is! _OneByteString) {
+      if (e._cid != _OneByteString._classId) {
         return _concatAllNative(strings);
       }
       totalLength += e.length;
@@ -500,6 +501,8 @@
 
 
 class _OneByteString extends _StringBase implements String {
+  static final int _classId = "A"._cid;
+
   factory _OneByteString._uninstantiable() {
     throw new UnsupportedError(
         "_OneByteString can only be allocated by the VM");
@@ -523,7 +526,7 @@
       native "OneByteString_splitWithCharCode";
 
   List<String> split(Pattern pattern) {
-    if ((pattern is _OneByteString) && (pattern.length == 1)) {
+    if ((pattern._cid == _OneByteString._classId) && (pattern.length == 1)) {
       return _splitWithCharCode(pattern.codeUnitAt(0));
     }
     return super.split(pattern);
@@ -627,23 +630,6 @@
 }
 
 
-class _ExternalFourByteString extends _StringBase implements String {
-  factory _ExternalFourByteString._uninstantiable() {
-    throw new UnsupportedError(
-        "ExternalFourByteString can only be allocated by the VM");
-  }
-
-  // Checks for one-byte whitespaces only.
-  // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
-  // whitespaces. Add checking for multi-byte whitespace codepoints.
-  bool _isWhitespace(int codePoint) {
-    return
-      (codePoint == 32) || // Space.
-      ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
-  }
-}
-
-
 class _StringMatch implements Match {
   const _StringMatch(int this.start,
                      String this.str,
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 56891a5..e9c6148 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -81,6 +81,14 @@
     return *this;
   }
 
+  bool Equals(const Operand& other) {
+    if (length_ != other.length_) return false;
+    for (uint8_t i = 0; i < length_; i++) {
+      if (encoding_[i] != other.encoding_[i]) return false;
+    }
+    return true;
+  }
+
  protected:
   Operand() : length_(0) { }  // Needed by subclass Address.
 
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 7572d0e..c213506 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -91,6 +91,15 @@
     return *this;
   }
 
+  bool Equals(const Operand& other) {
+    if (length_ != other.length_) return false;
+    if (rex_ != other.rex_) return false;
+    for (uint8_t i = 0; i < length_; i++) {
+      if (encoding_[i] != other.encoding_[i]) return false;
+    }
+    return true;
+  }
+
  protected:
   Operand() : length_(0), rex_(REX_NONE) { }  // Needed by subclass Address.
 
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 651ce74..a7adc56 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -18,6 +18,7 @@
   V(Object_runtimeType, 1)                                                     \
   V(Object_instanceOf, 5)                                                      \
   V(Object_as, 4)                                                              \
+  V(Object_cid, 1)                                                             \
   V(Function_apply, 2)                                                         \
   V(InvocationMirror_invoke, 4)                                                \
   V(AbstractType_toString, 1)                                                  \
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index d4a4ce2..c614a9c 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -805,6 +805,16 @@
 }
 
 
+// Gets called from debug stub when code reaches a breakpoint before
+// calling a closure.
+DEFINE_RUNTIME_ENTRY(BreakpointClosureHandler, 0) {
+  ASSERT(arguments.ArgCount() ==
+         kBreakpointClosureHandlerRuntimeEntry.argument_count());
+  ASSERT(isolate->debugger() != NULL);
+  isolate->debugger()->SignalBpReached();
+}
+
+
 // Gets called from debug stub when code reaches a breakpoint.
 DEFINE_RUNTIME_ENTRY(BreakpointStaticHandler, 0) {
   ASSERT(arguments.ArgCount() ==
@@ -1479,19 +1489,20 @@
   // are copied into local space at method entry).
   const intptr_t num_args =
       function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
-  // FP, PC-marker and return-address will be copied as well.
+  // The fixed size section of the (fake) Dart frame called via a stub by the
+  // optimized function contains FP, PP (ARM and MIPS only), PC-marker and
+  // return-address. This section is copied as well, so that its contained
+  // values can be updated before returning to the deoptimized function.
   const intptr_t frame_copy_size =
-      // Deoptimized function's return address: caller_frame->pc().
-      - kSavedPcSlotFromSp
-      + ((frame.fp() - frame.sp()) / kWordSize)
+      + kDartFrameFixedSize  // For saved values below sp.
+      + ((frame.fp() - frame.sp()) / kWordSize)  // For frame size incl. sp.
       + 1  // For fp.
-      + kParamEndSlotFromFp
-      + num_args;
+      + kParamEndSlotFromFp  // For saved values above fp.
+      + num_args;  // For arguments.
   intptr_t* frame_copy = new intptr_t[frame_copy_size];
   ASSERT(frame_copy != NULL);
-  // Include the return address of optimized code.
   intptr_t* start = reinterpret_cast<intptr_t*>(
-      frame.sp() + (kSavedPcSlotFromSp * kWordSize));
+      frame.sp() - (kDartFrameFixedSize * kWordSize));
   for (intptr_t i = 0; i < frame_copy_size; i++) {
     frame_copy[i] = *(start + i);
   }
@@ -1507,12 +1518,11 @@
   StackZone zone(isolate);
   HANDLESCOPE(isolate);
 
-  // All registers have been saved below last-fp.
-  // Note that the deopt stub is not allowed to save any other values (pc
-  // marker, pool pointer, alignment, etc...) below last-fp.
-  const uword last_fp = saved_registers_address +
-                        kNumberOfCpuRegisters * kWordSize +
-                        kNumberOfFpuRegisters * kFpuRegisterSize;
+  // All registers have been saved below last-fp as if they were locals.
+  const uword last_fp = saved_registers_address
+                        + (kNumberOfCpuRegisters * kWordSize)
+                        + (kNumberOfFpuRegisters * kFpuRegisterSize)
+                        - ((kFirstLocalSlotFromFp + 1) * kWordSize);
   CopySavedRegisters(saved_registers_address);
 
   // Get optimized code and frame that need to be deoptimized.
@@ -1545,20 +1555,21 @@
   const Function& function = Function::Handle(optimized_code.function());
   const intptr_t num_args =
       function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
-  intptr_t unoptimized_stack_size =
+  const intptr_t unoptimized_stack_size =
       + deopt_info.FrameSize()
+      - kDartFrameFixedSize
       - num_args
       - kParamEndSlotFromFp
       - 1;  // For fp.
-  return unoptimized_stack_size * kWordSize;
+  return unoptimized_stack_size * kWordSize;  // Stack size (FP - SP) in bytes.
 }
 END_LEAF_RUNTIME_ENTRY
 
 
-static intptr_t DeoptimizeWithDeoptInfo(const Code& code,
-                                        const DeoptInfo& deopt_info,
-                                        const StackFrame& caller_frame,
-                                        intptr_t deopt_reason) {
+static void DeoptimizeWithDeoptInfo(const Code& code,
+                                    const DeoptInfo& deopt_info,
+                                    const StackFrame& caller_frame,
+                                    intptr_t deopt_reason) {
   const intptr_t len = deopt_info.TranslationLength();
   GrowableArray<DeoptInstr*> deopt_instructions(len);
   const Array& deopt_table = Array::Handle(code.deopt_info_array());
@@ -1566,12 +1577,12 @@
   deopt_info.ToInstructions(deopt_table, &deopt_instructions);
 
   intptr_t* start = reinterpret_cast<intptr_t*>(
-      caller_frame.sp() + (kSavedPcSlotFromSp * kWordSize));
+      caller_frame.sp() - (kDartFrameFixedSize * kWordSize));
   const Function& function = Function::Handle(code.function());
   const intptr_t num_args =
       function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
   const intptr_t to_frame_size =
-      - kSavedPcSlotFromSp  // Deoptimized function's return address.
+      + kDartFrameFixedSize  // For saved values below sp.
       + (caller_frame.fp() - caller_frame.sp()) / kWordSize
       + 1  // For fp.
       + kParamEndSlotFromFp
@@ -1593,7 +1604,7 @@
   // right before control switches to the unoptimized code.
   const intptr_t num_materializations = len - frame_size;
   Isolate::Current()->PrepareForDeferredMaterialization(num_materializations);
-  for (intptr_t from_index = 0, to_index = 1;
+  for (intptr_t from_index = 0, to_index = kDartFrameFixedSize;
        from_index < num_materializations;
        from_index++) {
     const intptr_t field_count =
@@ -1621,13 +1632,12 @@
                    deopt_instructions[i + (len - frame_size)]->ToCString());
     }
   }
-  return deopt_context.GetCallerFp();
 }
 
 
 // The stack has been adjusted to fit all values for unoptimized frame.
 // Fill the unoptimized frame.
-DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeFillFrame, uword last_fp) {
+DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp) {
   Isolate* isolate = Isolate::Current();
   StackZone zone(isolate);
   HANDLESCOPE(isolate);
@@ -1651,10 +1661,10 @@
       optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason));
   ASSERT(!deopt_info.IsNull());
 
-  const intptr_t caller_fp = DeoptimizeWithDeoptInfo(optimized_code,
-                                                     deopt_info,
-                                                     *caller_frame,
-                                                     deopt_reason);
+  DeoptimizeWithDeoptInfo(optimized_code,
+                          deopt_info,
+                          *caller_frame,
+                          deopt_reason);
 
   isolate->SetDeoptFrameCopy(NULL, 0);
   isolate->set_deopt_cpu_registers_copy(NULL);
@@ -1662,8 +1672,6 @@
   delete[] frame_copy;
   delete[] cpu_registers_copy;
   delete[] fpu_registers_copy;
-
-  return caller_fp;
 }
 END_LEAF_RUNTIME_ENTRY
 
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index dcea908..a7d81d1 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -24,6 +24,7 @@
 DECLARE_RUNTIME_ENTRY(AllocateObject);
 DECLARE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck);
 DECLARE_RUNTIME_ENTRY(ArgumentDefinitionTest);
+DECLARE_RUNTIME_ENTRY(BreakpointClosureHandler);
 DECLARE_RUNTIME_ENTRY(BreakpointStaticHandler);
 DECLARE_RUNTIME_ENTRY(BreakpointReturnHandler);
 DECLARE_RUNTIME_ENTRY(BreakpointDynamicHandler);
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index ddf5c73..70d26fd 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -56,6 +56,11 @@
                                  ICData* ic_data,
                                  Array* arguments_descriptor);
 
+  // Return the arguments descriptor array of the closure call
+  // before the given return address.
+  static RawArray* GetClosureArgDescAt(uword return_address,
+                                       const Code& code);
+
   static intptr_t InstanceCallSizeInBytes();
 
   static void InsertCallAt(uword start, uword target);
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index 7109795..0dbb42c 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -12,6 +12,14 @@
 
 namespace dart {
 
+RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
+                                           const Code& code) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  CallPattern call(return_address, code);
+  return call.ArgumentsDescriptor();
+}
+
+
 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
                                          const Code& code) {
   ASSERT(code.ContainsInstructionAt(return_address));
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc
index c9ab14c..45ddb0b 100644
--- a/runtime/vm/code_patcher_ia32.cc
+++ b/runtime/vm/code_patcher_ia32.cc
@@ -141,6 +141,51 @@
 };
 
 
+// The expected pattern of a dart closure call:
+//   mov EDX, arguments_descriptor_array
+//   call target_address
+//   <- return address
+class ClosureCall : public ValueObject {
+ public:
+  explicit ClosureCall(uword return_address)
+      : start_(return_address - (kInstr1Size + kInstr2Size)) {
+    ASSERT(IsValid(return_address));
+    ASSERT(kInstr2Size == Assembler::kCallExternalLabelSize);
+  }
+
+  static bool IsValid(uword return_address) {
+    uint8_t* code_bytes = reinterpret_cast<uint8_t*>(
+        return_address - (kInstr1Size + kInstr2Size));
+    return (code_bytes[0] == 0xBA) && (code_bytes[kInstr1Size] == 0xE8);
+  }
+
+  RawArray* arguments_descriptor() const {
+    return *reinterpret_cast<RawArray**>(start_ + 1);
+  }
+
+ private:
+  static const int kInstr1Size = 5;  // mov EDX, arguments descriptor array
+  static const int kInstr2Size = 5;  // call stub
+
+  uword return_address() const {
+    return start_ + kInstr1Size + kInstr2Size;
+  }
+  uword call_address() const { return start_; }
+
+  uword start_;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
+};
+
+
+
+RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
+                                           const Code& code) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  ClosureCall call(return_address);
+  return call.arguments_descriptor();
+}
+
+
 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
                                          const Code& code) {
   ASSERT(code.ContainsInstructionAt(return_address));
diff --git a/runtime/vm/code_patcher_mips.cc b/runtime/vm/code_patcher_mips.cc
index d355a14..96088fd 100644
--- a/runtime/vm/code_patcher_mips.cc
+++ b/runtime/vm/code_patcher_mips.cc
@@ -12,6 +12,14 @@
 
 namespace dart {
 
+RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
+                                           const Code& code) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  CallPattern call(return_address, code);
+  return call.ArgumentsDescriptor();
+}
+
+
 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
                                          const Code& code) {
   ASSERT(code.ContainsInstructionAt(return_address));
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc
index 337892d..82652d0 100644
--- a/runtime/vm/code_patcher_x64.cc
+++ b/runtime/vm/code_patcher_x64.cc
@@ -125,6 +125,46 @@
 };
 
 
+// The expected code pattern of a dart closure call:
+//  00: 49 ba imm64  mov R10, immediate 2      ; 10 bytes
+//  10: 49 bb imm64  mov R11, target_address   ; 10 bytes
+//  20: 41 ff d3     call R11                  ; 3 bytes
+//  23: <- return_address
+class ClosureCall : public ValueObject {
+ public:
+  explicit ClosureCall(uword return_address)
+      : start_(return_address - kCallPatternSize) {
+    ASSERT(IsValid(return_address));
+  }
+
+  static bool IsValid(uword return_address) {
+    uint8_t* code_bytes =
+        reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
+    return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
+           (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) &&
+           (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) &&
+           (code_bytes[22] == 0xD3);
+  }
+
+  RawArray* arguments_descriptor() const {
+    return *reinterpret_cast<RawArray**>(start_ + 2);
+  }
+
+ private:
+  static const int kCallPatternSize = 10 + 10 + 3;
+  uword start_;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
+};
+
+
+RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
+                                           const Code& code) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  ClosureCall call(return_address);
+  return call.arguments_descriptor();
+}
+
+
 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
                                          const Code& code) {
   ASSERT(code.ContainsInstructionAt(return_address));
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index a16d853..696dbb2 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -295,6 +295,9 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
       }
 
+      // Optimize try-blocks.
+      TryCatchAnalyzer::Optimize(flow_graph);
+
       // Detach environments from the instructions that can't deoptimize.
       // Do it before we attempt to perform allocation sinking to minimize
       // amount of materializations it has to perform.
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index c125731..cb63b40 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -603,6 +603,7 @@
   breakpoint_kind_ = desc.DescriptorKind(pc_desc_index);
   ASSERT((breakpoint_kind_ == PcDescriptors::kIcCall) ||
          (breakpoint_kind_ == PcDescriptors::kFuncCall) ||
+         (breakpoint_kind_ == PcDescriptors::kClosureCall) ||
          (breakpoint_kind_ == PcDescriptors::kReturn));
 }
 
@@ -665,6 +666,15 @@
                                      StubCode::BreakpointStaticEntryPoint());
       break;
     }
+    case PcDescriptors::kClosureCall: {
+      const Code& code =
+          Code::Handle(Function::Handle(function_).unoptimized_code());
+      saved_bytes_.target_address_ =
+          CodePatcher::GetStaticCallTargetAt(pc_, code);
+      CodePatcher::PatchStaticCallAt(pc_, code,
+                                     StubCode::BreakpointClosureEntryPoint());
+      break;
+    }
     case PcDescriptors::kReturn:
       PatchFunctionReturn();
       break;
@@ -685,7 +695,8 @@
                                        saved_bytes_.target_address_);
       break;
     }
-    case PcDescriptors::kFuncCall: {
+    case PcDescriptors::kFuncCall:
+    case PcDescriptors::kClosureCall: {
       const Code& code =
           Code::Handle(Function::Handle(function_).unoptimized_code());
       CodePatcher::PatchStaticCallAt(pc_, code,
@@ -874,6 +885,7 @@
     PcDescriptors::Kind kind = desc.DescriptorKind(i);
     if ((kind == PcDescriptors::kIcCall) ||
         (kind == PcDescriptors::kFuncCall) ||
+        (kind == PcDescriptors::kClosureCall) ||
         (kind == PcDescriptors::kReturn)) {
       bpt = new CodeBreakpoint(target_function, i);
       RegisterCodeBreakpoint(bpt);
@@ -1041,6 +1053,7 @@
     PcDescriptors::Kind kind = desc.DescriptorKind(i);
     if ((kind == PcDescriptors::kIcCall) ||
         (kind == PcDescriptors::kFuncCall) ||
+        (kind == PcDescriptors::kClosureCall) ||
         (kind == PcDescriptors::kReturn)) {
       if ((desc_token_pos - first_token_pos) < best_fit) {
         best_fit = desc_token_pos - first_token_pos;
@@ -1573,6 +1586,25 @@
       if (IsDebuggable(callee)) {
         func_to_instrument = callee.raw();
       }
+    } else if (bpt->breakpoint_kind_ == PcDescriptors::kClosureCall) {
+      func_to_instrument = bpt->function();
+      const Code& code = Code::Handle(func_to_instrument.CurrentCode());
+      ArgumentsDescriptor args_desc(Array::Handle(
+          CodePatcher::GetClosureArgDescAt(bpt->pc_, code)));
+      ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0);
+      const Object& receiver =
+          Object::Handle(top_frame->GetClosureObject(args_desc.Count()));
+      if (!receiver.IsNull()) {
+        // Verify that the class of receiver is a closure class
+        // by checking that signature_function() is not null.
+        const Class& receiver_class = Class::Handle(receiver.clazz());
+        if (receiver_class.IsSignatureClass()) {
+          func_to_instrument = Closure::function(Instance::Cast(receiver));
+        }
+        // If the receiver is not a closure, then the runtime will attempt
+        // to invoke the "call" method on the object if one exists.
+        // TODO(hausner): find call method and intrument it for stepping.
+      }
     } else {
       ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn);
       // Treat like stepping out to caller.
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 9291b91..a7d3685 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -170,6 +170,7 @@
   void GetDescIndices();
   RawInstance* GetLocalVarValue(intptr_t slot_index);
   RawInstance* GetInstanceCallReceiver(intptr_t num_actual_args);
+  RawObject* GetClosureObject(intptr_t num_acatual_args);
 
   uword pc_;
   uword fp_;
diff --git a/runtime/vm/debugger_arm.cc b/runtime/vm/debugger_arm.cc
index 67a9e97..89e68a1 100644
--- a/runtime/vm/debugger_arm.cc
+++ b/runtime/vm/debugger_arm.cc
@@ -30,6 +30,16 @@
 }
 
 
+RawObject* ActivationFrame::GetClosureObject(intptr_t num_actual_args) {
+  // At a minimum we have the closure object on the stack.
+  ASSERT(num_actual_args > 0);
+  // Stack pointer points to last argument that was pushed on the stack.
+  uword closure_addr = sp() + ((num_actual_args - 1) * kWordSize);
+  return reinterpret_cast<RawObject*>(
+             *reinterpret_cast<uword*>(closure_addr));
+}
+
+
 void CodeBreakpoint::PatchFunctionReturn() {
   uword* code = reinterpret_cast<uword*>(pc_ - 3 * Instr::kInstrSize);
   ASSERT(code[0] == 0xe8bd4c00);  // ldmia sp!, {pp, fp, lr}
diff --git a/runtime/vm/debugger_ia32.cc b/runtime/vm/debugger_ia32.cc
index bd443ef..496a551 100644
--- a/runtime/vm/debugger_ia32.cc
+++ b/runtime/vm/debugger_ia32.cc
@@ -35,6 +35,16 @@
 }
 
 
+RawObject* ActivationFrame::GetClosureObject(intptr_t num_actual_args) {
+  // At a minimum we have the closure object on the stack.
+  ASSERT(num_actual_args > 0);
+  // Stack pointer points to last argument that was pushed on the stack.
+  uword closure_addr = sp() + ((num_actual_args - 1) * kWordSize);
+  return reinterpret_cast<RawObject*>(
+      *reinterpret_cast<uword*>(closure_addr));
+}
+
+
 void CodeBreakpoint::PatchFunctionReturn() {
   uint8_t* code = reinterpret_cast<uint8_t*>(pc_ - 5);
   ASSERT((code[0] == 0x89) && (code[1] == 0xEC));  // mov esp,ebp
diff --git a/runtime/vm/debugger_mips.cc b/runtime/vm/debugger_mips.cc
index dcf7df6..c35df1b 100644
--- a/runtime/vm/debugger_mips.cc
+++ b/runtime/vm/debugger_mips.cc
@@ -30,6 +30,16 @@
 }
 
 
+RawObject* ActivationFrame::GetClosureObject(intptr_t num_actual_args) {
+  // At a minimum we have the closure object on the stack.
+  ASSERT(num_actual_args > 0);
+  // Stack pointer points to last argument that was pushed on the stack.
+  uword closure_addr = sp() + ((num_actual_args - 1) * kWordSize);
+  return reinterpret_cast<RawObject*>(
+             *reinterpret_cast<uword*>(closure_addr));
+}
+
+
 void CodeBreakpoint::PatchFunctionReturn() {
   Instr* instr1 = Instr::At(pc_ - 5 * Instr::kInstrSize);
   Instr* instr2 = Instr::At(pc_ - 4 * Instr::kInstrSize);
diff --git a/runtime/vm/debugger_x64.cc b/runtime/vm/debugger_x64.cc
index c439640..29d3b33 100644
--- a/runtime/vm/debugger_x64.cc
+++ b/runtime/vm/debugger_x64.cc
@@ -30,6 +30,16 @@
 }
 
 
+RawObject* ActivationFrame::GetClosureObject(intptr_t num_actual_args) {
+  // At a minimum we have the closure object on the stack.
+  ASSERT(num_actual_args > 0);
+  // Stack pointer points to last argument that was pushed on the stack.
+  uword closure_addr = sp() + ((num_actual_args - 1) * kWordSize);
+  return reinterpret_cast<RawObject*>(
+             *reinterpret_cast<uword*>(closure_addr));
+}
+
+
 void CodeBreakpoint::PatchFunctionReturn() {
   uint8_t* code = reinterpret_cast<uint8_t*>(pc_ - 13);
   // movq %rbp,%rsp
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 9054358..717d867 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -36,12 +36,21 @@
   from_frame_size_ = isolate_->deopt_frame_copy_size();
   registers_copy_ = isolate_->deopt_cpu_registers_copy();
   fpu_registers_copy_ = isolate_->deopt_fpu_registers_copy();
+  // The deoptimized frame is filled starting just below the sp of its caller
+  // down to kDartFrameFixedSize words below its own sp.
+  // The chain of frame pointers is recreated from the fp of the caller.
   caller_fp_ = GetFromFp();
 }
 
 
 intptr_t DeoptimizationContext::GetFromFp() const {
-  return from_frame_[from_frame_size_ - num_args_ - 1 - kParamEndSlotFromFp];
+  return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp];
+}
+
+
+intptr_t DeoptimizationContext::GetFromPp() const {
+  return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp +
+      StackFrame::SavedCallerPpSlotFromFp()];
 }
 
 
@@ -49,14 +58,17 @@
   return from_frame_[from_frame_size_ - num_args_ + kSavedPcSlotFromSp];
 }
 
+
 intptr_t DeoptimizationContext::GetCallerFp() const {
   return caller_fp_;
 }
 
+
 void DeoptimizationContext::SetCallerFp(intptr_t caller_fp) {
   caller_fp_ = caller_fp;
 }
 
+
 // Deoptimization instruction moving value from optimized frame at
 // 'from_index' to specified slots in the unoptimized frame.
 // 'from_index' represents the slot index of the frame (0 being first argument)
@@ -476,6 +488,11 @@
   void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
     Function& function = Function::Handle(deopt_context->isolate());
     function ^= deopt_context->ObjectAt(object_table_index_);
+    if (function.IsNull()) {
+      // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0.
+      *to_addr = 0;
+      return;
+    }
     const Code& code =
         Code::Handle(deopt_context->isolate(), function.unoptimized_code());
     ASSERT(!code.IsNull());
@@ -503,6 +520,40 @@
 };
 
 
+// Deoptimization instruction creating a pool pointer for the code of
+// function at 'object_table_index'.
+class DeoptPpInstr : public DeoptInstr {
+ public:
+  explicit DeoptPpInstr(intptr_t object_table_index)
+      : object_table_index_(object_table_index) {
+    ASSERT(object_table_index >= 0);
+  }
+
+  virtual intptr_t from_index() const { return object_table_index_; }
+  virtual DeoptInstr::Kind kind() const { return kPp; }
+
+  virtual const char* ToCString() const {
+    return Isolate::Current()->current_zone()->PrintToString(
+        "pp oti:%"Pd"", object_table_index_);
+  }
+
+  void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
+    Function& function = Function::Handle(deopt_context->isolate());
+    function ^= deopt_context->ObjectAt(object_table_index_);
+    const Code& code =
+        Code::Handle(deopt_context->isolate(), function.unoptimized_code());
+    ASSERT(!code.IsNull());
+    const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool());
+    *to_addr = pp;
+  }
+
+ private:
+  intptr_t object_table_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr);
+};
+
+
 // Deoptimization instruction copying the caller saved FP from optimized frame.
 class DeoptCallerFpInstr : public DeoptInstr {
  public:
@@ -517,7 +568,8 @@
 
   void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
     *to_addr = deopt_context->GetCallerFp();
-    deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr));
+    deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(
+        to_addr - (kSavedCallerFpSlotFromFp * kWordSize)));
   }
 
  private:
@@ -525,6 +577,27 @@
 };
 
 
+// Deoptimization instruction copying the caller saved PP from optimized frame.
+class DeoptCallerPpInstr : public DeoptInstr {
+ public:
+  DeoptCallerPpInstr() {}
+
+  virtual intptr_t from_index() const { return 0; }
+  virtual DeoptInstr::Kind kind() const { return kCallerPp; }
+
+  virtual const char* ToCString() const {
+    return "callerpp";
+  }
+
+  void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) {
+    *to_addr = deopt_context->GetFromPp();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr);
+};
+
+
 // Deoptimization instruction copying the caller return address from optimized
 // frame.
 class DeoptCallerPcInstr : public DeoptInstr {
@@ -702,7 +775,9 @@
     case kUint32x4FpuRegister:
         return new DeoptUint32x4FpuRegisterInstr(from_index);
     case kPcMarker: return new DeoptPcMarkerInstr(from_index);
+    case kPp: return new DeoptPpInstr(from_index);
     case kCallerFp: return new DeoptCallerFpInstr();
+    case kCallerPp: return new DeoptCallerPpInstr();
     case kCallerPc: return new DeoptCallerPcInstr();
     case kSuffix: return new DeoptSuffixInstr(from_index);
     case kMaterializedObjectRef:
@@ -795,10 +870,16 @@
 
 void DeoptInfoBuilder::AddPcMarker(const Function& function,
                                    intptr_t to_index) {
-  // Function object was already added by AddReturnAddress, find it.
-  intptr_t from_index = FindOrAddObjectInTable(function);
+  intptr_t object_table_index = FindOrAddObjectInTable(function);
   ASSERT(to_index == FrameSize());
-  instructions_.Add(new DeoptPcMarkerInstr(from_index));
+  instructions_.Add(new DeoptPcMarkerInstr(object_table_index));
+}
+
+
+void DeoptInfoBuilder::AddPp(const Function& function, intptr_t to_index) {
+  intptr_t object_table_index = FindOrAddObjectInTable(function);
+  ASSERT(to_index == FrameSize());
+  instructions_.Add(new DeoptPpInstr(object_table_index));
 }
 
 
@@ -864,6 +945,12 @@
 }
 
 
+void DeoptInfoBuilder::AddCallerPp(intptr_t to_index) {
+  ASSERT(to_index == FrameSize());
+  instructions_.Add(new DeoptCallerPpInstr());
+}
+
+
 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) {
   ASSERT(to_index == FrameSize());
   instructions_.Add(new DeoptCallerPcInstr());
@@ -898,20 +985,20 @@
 }
 
 
-intptr_t DeoptInfoBuilder::EmitMaterializationArguments() {
-  intptr_t slot_idx = 1;  // Return address is emitted at 0.
+intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t to_index) {
+  ASSERT(to_index == kDartFrameFixedSize);
   for (intptr_t i = 0; i < materializations_.length(); i++) {
     MaterializeObjectInstr* mat = materializations_[i];
-    AddConstant(mat->cls(), slot_idx++);  // Class of the instance to allocate.
+    AddConstant(mat->cls(), to_index++);  // Class of the instance to allocate.
     for (intptr_t i = 0; i < mat->InputCount(); i++) {
       if (!mat->InputAt(i)->BindsToConstantNull()) {
         // Emit field-value pair.
-        AddConstant(mat->FieldAt(i), slot_idx++);
-        AddCopy(mat->InputAt(i), mat->LocationAt(i), slot_idx++);
+        AddConstant(mat->FieldAt(i), to_index++);
+        AddCopy(mat->InputAt(i), mat->LocationAt(i), to_index++);
       }
     }
   }
-  return slot_idx;
+  return to_index;
 }
 
 
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 024eb93..a7c8ab9 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -20,9 +20,9 @@
 // Holds all data relevant for execution of deoptimization instructions.
 class DeoptimizationContext : public ValueObject {
  public:
-  // 'to_frame_start' points to the return address just below the frame's
-  // stack pointer (kPcAddressOffsetFromSp). 'num_args' is 0 if there are no
-  // arguments or if there are optional arguments.
+  // 'to_frame_start' points to the fixed size portion of the frame under sp.
+  // 'num_args' is 0 if there are no arguments or if there are optional
+  // arguments.
   DeoptimizationContext(intptr_t* to_frame_start,
                         intptr_t to_frame_size,
                         const Array& object_table,
@@ -40,6 +40,7 @@
   }
 
   intptr_t GetFromFp() const;
+  intptr_t GetFromPp() const;
   intptr_t GetFromPc() const;
 
   intptr_t GetCallerFp() const;
@@ -109,7 +110,9 @@
     kFloat32x4StackSlot,
     kUint32x4StackSlot,
     kPcMarker,
+    kPp,
     kCallerFp,
+    kCallerPp,
     kCallerPc,
     kSuffix,
     kMaterializedObjectRef,
@@ -180,7 +183,9 @@
   // Copy from optimized frame to unoptimized.
   void AddCopy(Value* value, const Location& from_loc, intptr_t to_index);
   void AddPcMarker(const Function& function, intptr_t to_index);
+  void AddPp(const Function& function, intptr_t to_index);
   void AddCallerFp(intptr_t to_index);
+  void AddCallerPp(intptr_t to_index);
   void AddCallerPc(intptr_t to_index);
 
   // Add object to be materialized. Emit kMaterializeObject instruction.
@@ -189,13 +194,13 @@
   // For every materialized object emit instructions describing data required
   // for materialization: class of the instance to allocate and field-value
   // pairs for initialization.
-  // Emitted instructions are expected to follow return-address slot emitted
-  // first. This way they become a part of the bottom-most deoptimized frame
-  // and are discoverable by GC.
+  // Emitted instructions are expected to follow fixed size section of frame
+  // emitted first. This way they become a part of the bottom-most deoptimized
+  // frame and are discoverable by GC.
   // At deoptimization they will be removed by the stub at the very end:
   // after they were used to materialize objects.
   // Returns the index of the next stack slot. Used for verification.
-  intptr_t EmitMaterializationArguments();
+  intptr_t EmitMaterializationArguments(intptr_t to_index);
 
   RawDeoptInfo* CreateDeoptInfo();
 
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index ae130d4..8ebce64 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -15,6 +15,12 @@
 DECLARE_FLAG(bool, trace_optimization);
 DECLARE_FLAG(bool, verify_compiler);
 
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
+DEFINE_FLAG(bool, optimize_try_catch, false, "Optimization of try-catch");
+#else
+DEFINE_FLAG(bool, optimize_try_catch, true, "Optimization of try-catch");
+#endif
+
 FlowGraph::FlowGraph(const FlowGraphBuilder& builder,
                      GraphEntryInstr* graph_entry,
                      intptr_t max_block_id)
@@ -30,7 +36,9 @@
     postorder_(),
     reverse_postorder_(),
     block_effects_(NULL),
-    licm_allowed_(true) {
+    licm_allowed_(true),
+    loop_headers_(NULL),
+    loop_invariant_loads_(NULL) {
   DiscoverBlocks();
 }
 
@@ -104,6 +112,8 @@
 
   // Block effects are using postorder numbering. Discard computed information.
   block_effects_ = NULL;
+  loop_headers_ = NULL;
+  loop_invariant_loads_ = NULL;
 }
 
 
@@ -328,8 +338,20 @@
     const intptr_t block_count = flow_graph_->preorder().length();
     for (intptr_t i = 0; i < block_count; i++) {
       BlockEntryInstr* block = flow_graph_->preorder()[i];
+      // All locals are assigned inside a try{} block.
+      // This is a safe approximation and workaround to force insertion of
+      // phis for stores that appear non-live because of the way catch-blocks
+      // are connected to the graph: They normally are dominated by the
+      // try-entry, but are direct successors of the graph entry in our flow
+      // graph.
+      // TODO(fschneider): Improve this approximation by better modeling the
+      // actual data flow to reduce the number of redundant phis.
       BitVector* kill = GetKillSet(block);
-      kill->Intersect(GetLiveOutSet(block));
+      if (block->InsideTryBlock()) {
+        kill->SetAll();
+      } else {
+        kill->Intersect(GetLiveOutSet(block));
+      }
       assigned_vars_.Add(kill);
     }
 
@@ -378,6 +400,17 @@
     BitVector* live_in = live_in_[i];
     last_loads->Clear();
 
+    // There is an implicit use (load-local) of every local variable at each
+    // call inside a try{} block and every call has an implicit control-flow
+    // to the catch entry. As an approximation we mark all locals as live
+    // inside try{}.
+    // TODO(fschneider): Improve this approximation, since not all local
+    // variable stores actually reach a call.
+    if (block->InsideTryBlock()) {
+      live_in->SetAll();
+      continue;
+    }
+
     // Iterate backwards starting at the last instruction.
     for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
       Instruction* current = it.Current();
@@ -617,8 +650,7 @@
 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
                        VariableLivenessAnalysis* variable_liveness,
                        ZoneGrowableArray<Definition*>* inlining_parameters) {
-  // TODO(fschneider): Support catch-entry.
-  if (graph_entry_->SuccessorCount() > 1) {
+  if (!FLAG_optimize_try_catch && (graph_entry_->SuccessorCount() > 1)) {
     Bailout("Catch-entry support in SSA.");
   }
 
@@ -653,9 +685,14 @@
     env.Add(constant_null());
   }
 
-  BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
-  ASSERT(normal_entry != NULL);  // Must have entry.
-  RenameRecursive(normal_entry, &env, live_phis, variable_liveness);
+  if (graph_entry_->SuccessorCount() > 1) {
+    // Functions with try-catch have a fixed area of stack slots reserved
+    // so that all local variables are stored at a known location when
+    // on entry to the catch.
+    graph_entry_->set_fixed_slot_count(
+        num_stack_locals() + num_copied_params());
+  }
+  RenameRecursive(graph_entry_, &env, live_phis, variable_liveness);
 }
 
 
@@ -689,9 +726,26 @@
         if (phi != NULL) {
           (*env)[i] = phi;
           phi->set_ssa_temp_index(alloc_ssa_temp_index());  // New SSA temp.
+          if (block_entry->InsideTryBlock()) {
+            // This is a safe approximation.  Inside try{} all locals are
+            // used at every call implicitly, so we mark all phis as live
+            // from the start.
+            // TODO(fschneider): Improve this approximation to eliminate
+            // more redundant phis.
+            phi->mark_alive();
+            live_phis->Add(phi);
+          }
         }
       }
     }
+  } else if (block_entry->IsCatchBlockEntry()) {
+    // Add real definitions for all locals and parameters.
+    for (intptr_t i = 0; i < env->length(); ++i) {
+      ParameterInstr* param = new ParameterInstr(i, block_entry);
+      param->set_ssa_temp_index(alloc_ssa_temp_index());  // New SSA temp.
+      (*env)[i] = param;
+      block_entry->AsCatchBlockEntry()->initial_definitions()->Add(param);
+    }
   }
 
   // Attach environment to the block entry.
@@ -907,8 +961,10 @@
 }
 
 
-void FlowGraph::ComputeLoops(GrowableArray<BlockEntryInstr*>* loop_headers) {
-  ASSERT(loop_headers->is_empty());
+ZoneGrowableArray<BlockEntryInstr*>* FlowGraph::ComputeLoops() {
+  ZoneGrowableArray<BlockEntryInstr*>* loop_headers =
+      new ZoneGrowableArray<BlockEntryInstr*>();
+
   for (BlockIterator it = postorder_iterator();
        !it.Done();
        it.Advance()) {
@@ -925,6 +981,8 @@
       }
     }
   }
+
+  return loop_headers;
 }
 
 
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index ec85594..597ef71 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -128,10 +128,6 @@
   void ComputeSSA(intptr_t next_virtual_register_number,
                   ZoneGrowableArray<Definition*>* inlining_parameters);
 
-  // Finds natural loops in the flow graph and attaches a list of loop
-  // body blocks for each loop header.
-  void ComputeLoops(GrowableArray<BlockEntryInstr*>* loop_headers);
-
   // TODO(zerny): Once the SSA is feature complete this should be removed.
   void Bailout(const char* reason) const;
 
@@ -167,6 +163,24 @@
   // after this point.
   void disallow_licm() { licm_allowed_ = false; }
 
+  const ZoneGrowableArray<BlockEntryInstr*>& loop_headers() {
+    if (loop_headers_ == NULL) {
+      loop_headers_ = ComputeLoops();
+    }
+    return *loop_headers_;
+  }
+
+  // Per loop header invariant loads sets. Each set contains load id for
+  // those loads that are not affected by anything in the loop and can be
+  // hoisted out. Sets are computed by LoadOptimizer.
+  ZoneGrowableArray<BitVector*>* loop_invariant_loads() const {
+    return loop_invariant_loads_;
+  }
+  void set_loop_invariant_loads(
+      ZoneGrowableArray<BitVector*>* loop_invariant_loads) {
+    loop_invariant_loads_ = loop_invariant_loads;
+  }
+
  private:
   friend class IfConverter;
   friend class BranchSimplifier;
@@ -202,6 +216,10 @@
   void ReplacePredecessor(BlockEntryInstr* old_block,
                           BlockEntryInstr* new_block);
 
+  // Finds natural loops in the flow graph and attaches a list of loop
+  // body blocks for each loop header.
+  ZoneGrowableArray<BlockEntryInstr*>* ComputeLoops();
+
   // DiscoverBlocks computes parent_ and assigned_vars_ which are then used
   // if/when computing SSA.
   GrowableArray<intptr_t> parent_;
@@ -223,6 +241,9 @@
 
   BlockEffects* block_effects_;
   bool licm_allowed_;
+
+  ZoneGrowableArray<BlockEntryInstr*>* loop_headers_;
+  ZoneGrowableArray<BitVector*>* loop_invariant_loads_;
 };
 
 
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 5c16a8b..fddde80 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -178,6 +178,17 @@
           }
         }
       }
+    } else if (block->IsCatchBlockEntry()) {
+      // Process initial definitions.
+      CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
+      for (intptr_t i = 0;
+           i < catch_entry->initial_definitions()->length();
+           i++) {
+        intptr_t vreg =
+            (*catch_entry->initial_definitions())[i]->ssa_temp_index();
+        kill_[catch_entry->postorder_number()]->Add(vreg);
+        live_in_[catch_entry->postorder_number()]->Remove(vreg);
+      }
     }
   }
 
@@ -241,7 +252,7 @@
   ASSERT(start < end);
 
   // Live ranges are being build by visiting instructions in post-order.
-  // This implies that use intervals will be perpended in a monotonically
+  // This implies that use intervals will be prepended in a monotonically
   // decreasing order.
   if (first_use_interval() != NULL) {
     // If the first use interval and the use interval we are adding
@@ -488,7 +499,29 @@
       }
     }
 
-    ConnectIncomingPhiMoves(block);
+    if (block->IsJoinEntry()) {
+      ConnectIncomingPhiMoves(block->AsJoinEntry());
+    } else if (block->IsCatchBlockEntry()) {
+      // Process initial definitions.
+      CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
+      for (intptr_t i = 0;
+           i < catch_entry->initial_definitions()->length();
+           i++) {
+        Definition* defn = (*catch_entry->initial_definitions())[i];
+        LiveRange* range = GetLiveRange(defn->ssa_temp_index());
+        range->DefineAt(catch_entry->start_pos());  // Defined at block entry.
+
+        // Save range->End() because it may change in ProcessInitialDefinition.
+        intptr_t range_end = range->End();
+        ProcessInitialDefinition(defn, range, catch_entry);
+        spill_slots_.Add(range_end);
+        quad_spill_slots_.Add(false);
+
+        if (defn->IsParameter() && range->spill_slot().stack_index() >= 0) {
+          MarkAsObjectAtSafepoints(range);
+        }
+      }
+    }
   }
 
   // Process incoming parameters and constants.  Do this after all other
@@ -499,49 +532,56 @@
     LiveRange* range = GetLiveRange(defn->ssa_temp_index());
     range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
     range->DefineAt(graph_entry->start_pos());
-    if (defn->IsParameter()) {
-      ParameterInstr* param = defn->AsParameter();
-      // Assert that copied and non-copied parameters are mutually exclusive.
-      // This might change in the future and, if so, the index will be wrong.
-      ASSERT((flow_graph_.num_copied_params() == 0) ||
-             (flow_graph_.num_non_copied_params() == 0));
-      // Slot index for the leftmost copied parameter is 0.
-      intptr_t slot_index = param->index();
-      // Slot index for the rightmost fixed parameter is -1.
-      slot_index -= flow_graph_.num_non_copied_params();
 
-      range->set_assigned_location(Location::StackSlot(slot_index));
-      range->set_spill_slot(Location::StackSlot(slot_index));
-      if (flow_graph_.num_copied_params() > 0) {
-        ASSERT(spill_slots_.length() == slot_index);
-        spill_slots_.Add(range->End());
-        quad_spill_slots_.Add(false);
-      }
-    } else {
-      ConstantInstr* constant = defn->AsConstant();
-      ASSERT(constant != NULL);
-      range->set_assigned_location(Location::Constant(constant->value()));
-      range->set_spill_slot(Location::Constant(constant->value()));
-    }
-    AssignSafepoints(range);
-    range->finger()->Initialize(range);
-    UsePosition* use =
-        range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos());
-    if (use != NULL) {
-      LiveRange* tail =
-          SplitBetween(range, graph_entry->start_pos(), use->pos());
-      // Parameters and constants are tagged, so allocated to CPU registers.
-      CompleteRange(tail, Location::kRegister);
-    }
-    ConvertAllUses(range);
-
+    // Save range->End() because it may change in ProcessInitialDefinition.
+    intptr_t range_end = range->End();
+    ProcessInitialDefinition(defn, range, graph_entry);
     if (defn->IsParameter() && flow_graph_.num_copied_params() > 0) {
+      spill_slots_.Add(range_end);
+      quad_spill_slots_.Add(false);
+
       MarkAsObjectAtSafepoints(range);
     }
   }
 }
 
 
+void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn,
+                                                  LiveRange* range,
+                                                  BlockEntryInstr* block) {
+  if (defn->IsParameter()) {
+    ParameterInstr* param = defn->AsParameter();
+    // Assert that copied and non-copied parameters are mutually exclusive.
+    // This might change in the future and, if so, the index will be wrong.
+    ASSERT((flow_graph_.num_copied_params() == 0) ||
+           (flow_graph_.num_non_copied_params() == 0));
+    // Slot index for the leftmost copied parameter is 0.
+    intptr_t slot_index = param->index();
+    // Slot index for the rightmost fixed parameter is -1.
+    slot_index -= flow_graph_.num_non_copied_params();
+
+    range->set_assigned_location(Location::StackSlot(slot_index));
+    range->set_spill_slot(Location::StackSlot(slot_index));
+  } else {
+    ConstantInstr* constant = defn->AsConstant();
+    ASSERT(constant != NULL);
+    range->set_assigned_location(Location::Constant(constant->value()));
+    range->set_spill_slot(Location::Constant(constant->value()));
+  }
+  AssignSafepoints(range);
+  range->finger()->Initialize(range);
+  UsePosition* use =
+      range->finger()->FirstRegisterBeneficialUse(block->start_pos());
+  if (use != NULL) {
+    LiveRange* tail =
+        SplitBetween(range, block->start_pos(), use->pos());
+    // Parameters and constants are tagged, so allocated to CPU registers.
+    CompleteRange(tail, Location::kRegister);
+  }
+  ConvertAllUses(range);
+}
+
+
 static Location::Kind RegisterKindFromPolicy(Location loc) {
   if (loc.policy() == Location::kRequiresFpuRegister) {
     return Location::kFpuRegister;
@@ -648,12 +688,9 @@
 }
 
 
-void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) {
-  // If this block is a join we need to add destinations of phi
-  // resolution moves to phi's live range so that register allocator will
-  // fill them with moves.
-  JoinEntryInstr* join = block->AsJoinEntry();
-  if (join == NULL) return;
+void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
+  // For join blocks we need to add destinations of phi resolution moves
+  // to phi's live range so that register allocator will fill them with moves.
 
   // All uses are recorded at the start position in the block.
   const intptr_t pos = join->start_pos();
@@ -676,7 +713,7 @@
     if (is_loop_header) range->mark_loop_phi();
 
     for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) {
-      BlockEntryInstr* pred = block->PredecessorAt(pred_idx);
+      BlockEntryInstr* pred = join->PredecessorAt(pred_idx);
       GotoInstr* goto_instr = pred->last_instruction()->AsGoto();
       ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove()));
       MoveOperands* move =
@@ -1558,7 +1595,11 @@
   // Search for a free spill slot among allocated: the value in it should be
   // dead and its type should match (e.g. it should not be a part of the quad if
   // we are allocating normal double slot).
-  intptr_t idx = 0;
+  // For CPU registers we need to take reserved slots for try-catch into
+  // account.
+  intptr_t idx = register_kind_ == Location::kRegister
+      ? flow_graph_.graph_entry()->fixed_slot_count()
+      : 0;
   for (; idx < spill_slots_.length(); idx++) {
     if ((need_quad == quad_spill_slots_[idx]) &&
         (spill_slots_[idx] <= start)) {
@@ -2450,6 +2491,17 @@
        !it.Done();
        it.Advance()) {
     BlockEntryInstr* block = it.Current();
+
+    // Catch entry.
+    if (block->IsCatchBlockEntry()) {
+      CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
+      for (intptr_t i = 0;
+           i < catch_entry->initial_definitions()->length();
+           ++i) {
+        Definition* def = (*catch_entry->initial_definitions())[i];
+        value_representations_[def->ssa_temp_index()] = def->representation();
+      }
+    }
     // Phis.
     if (block->IsJoinEntry()) {
       JoinEntryInstr* join = block->AsJoinEntry();
diff --git a/runtime/vm/flow_graph_allocator.h b/runtime/vm/flow_graph_allocator.h
index 0efca0c..5e9ec74 100644
--- a/runtime/vm/flow_graph_allocator.h
+++ b/runtime/vm/flow_graph_allocator.h
@@ -101,6 +101,7 @@
   // Visit instructions in the postorder and build live ranges for
   // all SSA values.
   void BuildLiveRanges();
+
   Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block,
                                        BitVector* interference_set);
   void ProcessEnvironmentUses(BlockEntryInstr* block, Instruction* current);
@@ -111,7 +112,10 @@
   void ProcessOneInstruction(BlockEntryInstr* block,
                              Instruction* instr,
                              BitVector* interference_set);
-  void ConnectIncomingPhiMoves(BlockEntryInstr* block);
+  void ProcessInitialDefinition(Definition* defn,
+                                LiveRange* range,
+                                BlockEntryInstr* block);
+  void ConnectIncomingPhiMoves(JoinEntryInstr* join);
   void BlockLocation(Location loc, intptr_t from, intptr_t to);
   void BlockRegisterLocation(Location loc,
                              intptr_t from,
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index ff98680..5142280 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -293,9 +293,12 @@
     }
   }
 
-  // Neither call nor callee entry are in the graph at this point. Remove them
-  // from use lists.
+  // Neither call nor callee entry nor the graph entry (if present) are in the
+  // graph at this point. Remove them from use lists.
   callee_entry->UnuseAllInputs();
+  if (callee_entry->PredecessorCount() > 0) {
+    callee_entry->PredecessorAt(0)->AsGraphEntry()->UnuseAllInputs();
+  }
   call_->UnuseAllInputs();
 }
 
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 222501c..7b0e38b 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -62,92 +62,6 @@
 }
 
 
-RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
-                                                 DeoptInfoBuilder* builder) {
-  if (deoptimization_env_ == NULL) return DeoptInfo::null();
-
-  intptr_t stack_height = compiler->StackSize();
-  AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
-
-  intptr_t slot_ix = 0;
-  Environment* current = deoptimization_env_;
-
-  // Emit all kMaterializeObject instructions describing objects to be
-  // materialized on the deoptimization as a prefix to the deoptimization info.
-  EmitMaterializations(deoptimization_env_, builder);
-
-  // The real frame starts here.
-  builder->MarkFrameStart();
-  builder->AddReturnAddress(current->function(),
-                            deopt_id(),
-                            slot_ix++);
-
-  // Emit all values that are needed for materialization as a part of the
-  // expression stack for the bottom-most frame. This guarantees that GC
-  // will be able to find them during materialization.
-  slot_ix = builder->EmitMaterializationArguments();
-
-  // For the innermost environment, set outgoing arguments and the locals.
-  for (intptr_t i = current->Length() - 1;
-       i >= current->fixed_parameter_count();
-       i--) {
-    builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
-  }
-
-  // PC marker and caller FP.
-  builder->AddPcMarker(current->function(), slot_ix++);
-  builder->AddCallerFp(slot_ix++);
-
-  Environment* previous = current;
-  current = current->outer();
-  while (current != NULL) {
-    // For any outer environment the deopt id is that of the call instruction
-    // which is recorded in the outer environment.
-    builder->AddReturnAddress(current->function(),
-                              Isolate::ToDeoptAfter(current->deopt_id()),
-                              slot_ix++);
-
-    // The values of outgoing arguments can be changed from the inlined call so
-    // we must read them from the previous environment.
-    for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
-      builder->AddCopy(previous->ValueAt(i),
-                       previous->LocationAt(i),
-                       slot_ix++);
-    }
-
-    // Set the locals, note that outgoing arguments are not in the environment.
-    for (intptr_t i = current->Length() - 1;
-         i >= current->fixed_parameter_count();
-         i--) {
-      builder->AddCopy(current->ValueAt(i),
-                       current->LocationAt(i),
-                       slot_ix++);
-    }
-
-    // PC marker and caller FP.
-    builder->AddPcMarker(current->function(), slot_ix++);
-    builder->AddCallerFp(slot_ix++);
-
-    // Iterate on the outer environment.
-    previous = current;
-    current = current->outer();
-  }
-  // The previous pointer is now the outermost environment.
-  ASSERT(previous != NULL);
-
-  // For the outermost environment, set caller PC.
-  builder->AddCallerPc(slot_ix++);
-
-  // For the outermost environment, set the incoming arguments.
-  for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
-    builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
-  }
-
-  const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
-  return deopt_info.raw();
-}
-
-
 FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler,
                                      const FlowGraph& flow_graph,
                                      bool is_optimizing)
@@ -341,7 +255,8 @@
 
 intptr_t FlowGraphCompiler::StackSize() const {
   if (is_optimizing_) {
-    return block_order_[0]->AsGraphEntry()->spill_slot_count();
+    GraphEntryInstr* entry = flow_graph_.graph_entry();
+    return entry->fixed_slot_count() + entry->spill_slot_count();
   } else {
     return parsed_function_.num_stack_locals() +
         parsed_function_.num_copied_params();
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index ffdf981..f301879 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -244,6 +244,9 @@
   const GrowableArray<BlockEntryInstr*>& block_order() const {
     return block_order_;
   }
+
+  const FlowGraph& flow_graph() const { return flow_graph_; }
+
   DescriptorList* pc_descriptors_list() const {
     return pc_descriptors_list_;
   }
@@ -380,6 +383,8 @@
   // Fallthrough calls super equality.
   void EmitSuperEqualityCallPrologue(Register result, Label* skip_call);
 
+  void EmitTrySync(Instruction* instr, intptr_t try_index);
+
   intptr_t StackSize() const;
 
   // Returns assembler label associated with the given block entry.
@@ -464,6 +469,8 @@
 
   void EmitFrameEntry();
 
+  void EmitTrySyncMove(Address dest, Location loc, bool* push_emitted);
+
   void AddStaticCallTarget(const Function& function);
 
   void GenerateDeferredCode();
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 6d32025..f7db7fe 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -10,6 +10,7 @@
 #include "lib/error.h"
 #include "vm/ast_printer.h"
 #include "vm/dart_entry.h"
+#include "vm/deopt_instructions.h"
 #include "vm/il_printer.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
@@ -42,6 +43,103 @@
 }
 
 
+RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+                                                 DeoptInfoBuilder* builder) {
+  if (deoptimization_env_ == NULL) return DeoptInfo::null();
+
+  intptr_t stack_height = compiler->StackSize();
+  AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
+
+  intptr_t slot_ix = 0;
+  Environment* current = deoptimization_env_;
+
+  // Emit all kMaterializeObject instructions describing objects to be
+  // materialized on the deoptimization as a prefix to the deoptimization info.
+  EmitMaterializations(deoptimization_env_, builder);
+
+  // The real frame starts here.
+  builder->MarkFrameStart();
+
+  // Current PP, FP, and PC.
+  builder->AddPp(current->function(), slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+  builder->AddReturnAddress(current->function(),
+                            deopt_id(),
+                            slot_ix++);
+
+  // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
+
+  // Emit all values that are needed for materialization as a part of the
+  // expression stack for the bottom-most frame. This guarantees that GC
+  // will be able to find them during materialization.
+  slot_ix = builder->EmitMaterializationArguments(slot_ix);
+
+  // For the innermost environment, set outgoing arguments and the locals.
+  for (intptr_t i = current->Length() - 1;
+       i >= current->fixed_parameter_count();
+       i--) {
+    builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
+  }
+
+  Environment* previous = current;
+  current = current->outer();
+  while (current != NULL) {
+    // PP, FP, and PC.
+    builder->AddPp(current->function(), slot_ix++);
+    builder->AddCallerFp(slot_ix++);
+
+    // For any outer environment the deopt id is that of the call instruction
+    // which is recorded in the outer environment.
+    builder->AddReturnAddress(current->function(),
+                              Isolate::ToDeoptAfter(current->deopt_id()),
+                              slot_ix++);
+
+    // PC marker.
+    builder->AddPcMarker(previous->function(), slot_ix++);
+
+    // The values of outgoing arguments can be changed from the inlined call so
+    // we must read them from the previous environment.
+    for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+      builder->AddCopy(previous->ValueAt(i),
+                       previous->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // Set the locals, note that outgoing arguments are not in the environment.
+    for (intptr_t i = current->Length() - 1;
+         i >= current->fixed_parameter_count();
+         i--) {
+      builder->AddCopy(current->ValueAt(i),
+                       current->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // Iterate on the outer environment.
+    previous = current;
+    current = current->outer();
+  }
+  // The previous pointer is now the outermost environment.
+  ASSERT(previous != NULL);
+
+  // For the outermost environment, set caller PC, caller PP, and caller FP.
+  builder->AddCallerPp(slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+  builder->AddCallerPc(slot_ix++);
+
+  // PC marker.
+  builder->AddPcMarker(previous->function(), slot_ix++);
+
+  // For the outermost environment, set the incoming arguments.
+  for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+    builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
+  }
+
+  const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+  return deopt_info.raw();
+}
+
+
 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
                                              intptr_t stub_ix) {
   // Calls do not need stubs, they share a deoptimization trampoline.
@@ -56,6 +154,7 @@
 
   __ BranchLink(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
+  __ bkpt(0);  // TODO(regis): Remove breakpoint to save space.
 #undef __
 }
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 13c4965..a4af2f8 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -10,6 +10,7 @@
 #include "lib/error.h"
 #include "vm/ast_printer.h"
 #include "vm/dart_entry.h"
+#include "vm/deopt_instructions.h"
 #include "vm/il_printer.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
@@ -45,6 +46,98 @@
 }
 
 
+RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+                                                 DeoptInfoBuilder* builder) {
+  if (deoptimization_env_ == NULL) return DeoptInfo::null();
+
+  intptr_t stack_height = compiler->StackSize();
+  AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
+
+  intptr_t slot_ix = 0;
+  Environment* current = deoptimization_env_;
+
+  // Emit all kMaterializeObject instructions describing objects to be
+  // materialized on the deoptimization as a prefix to the deoptimization info.
+  EmitMaterializations(deoptimization_env_, builder);
+
+  // The real frame starts here.
+  builder->MarkFrameStart();
+
+  // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
+
+  // Current FP and PC.
+  builder->AddCallerFp(slot_ix++);
+  builder->AddReturnAddress(current->function(),
+                            deopt_id(),
+                            slot_ix++);
+
+  // Emit all values that are needed for materialization as a part of the
+  // expression stack for the bottom-most frame. This guarantees that GC
+  // will be able to find them during materialization.
+  slot_ix = builder->EmitMaterializationArguments(slot_ix);
+
+  // For the innermost environment, set outgoing arguments and the locals.
+  for (intptr_t i = current->Length() - 1;
+       i >= current->fixed_parameter_count();
+       i--) {
+    builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
+  }
+
+  // Current PC marker and caller FP.
+  builder->AddPcMarker(current->function(), slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+
+  Environment* previous = current;
+  current = current->outer();
+  while (current != NULL) {
+    // For any outer environment the deopt id is that of the call instruction
+    // which is recorded in the outer environment.
+    builder->AddReturnAddress(current->function(),
+                              Isolate::ToDeoptAfter(current->deopt_id()),
+                              slot_ix++);
+
+    // The values of outgoing arguments can be changed from the inlined call so
+    // we must read them from the previous environment.
+    for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+      builder->AddCopy(previous->ValueAt(i),
+                       previous->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // Set the locals, note that outgoing arguments are not in the environment.
+    for (intptr_t i = current->Length() - 1;
+         i >= current->fixed_parameter_count();
+         i--) {
+      builder->AddCopy(current->ValueAt(i),
+                       current->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // PC marker and caller FP.
+    builder->AddPcMarker(current->function(), slot_ix++);
+    builder->AddCallerFp(slot_ix++);
+
+    // Iterate on the outer environment.
+    previous = current;
+    current = current->outer();
+  }
+  // The previous pointer is now the outermost environment.
+  ASSERT(previous != NULL);
+
+  // For the outermost environment, set caller PC.
+  builder->AddCallerPc(slot_ix++);
+
+  // For the outermost environment, set the incoming arguments.
+  for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+    builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
+  }
+
+  const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+  return deopt_info.raw();
+}
+
+
 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
                                              intptr_t stub_ix) {
   // Calls do not need stubs, they share a deoptimization trampoline.
@@ -59,6 +152,7 @@
 
   __ call(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
+  __ int3();
 #undef __
 }
 
@@ -646,6 +740,81 @@
                            Scanner::kDummyTokenIndex);
     }
     AllocateRegistersLocally(instr);
+  } else if (instr->MayThrow()  &&
+             (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) {
+    // Optimized try-block: Sync locals to fixed stack locations.
+    EmitTrySync(instr, CurrentTryIndex());
+  }
+}
+
+
+void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+                                        Location loc,
+                                        bool* push_emitted) {
+  if (loc.IsConstant()) {
+    if (!*push_emitted) {
+      __ pushl(EAX);
+      *push_emitted = true;
+    }
+    __ LoadObject(EAX, loc.constant());
+    __ movl(dest, EAX);
+  } else if (loc.IsRegister()) {
+    if (*push_emitted && loc.reg() == EAX) {
+      __ movl(EAX, Address(ESP, 0));
+      __ movl(dest, EAX);
+    } else {
+      __ movl(dest, loc.reg());
+    }
+  } else {
+    Address src = loc.ToStackSlotAddress();
+    if (!src.Equals(dest)) {
+      if (!*push_emitted) {
+        __ pushl(EAX);
+        *push_emitted = true;
+      }
+      __ movl(EAX, src);
+      __ movl(dest, EAX);
+    }
+  }
+}
+
+
+void FlowGraphCompiler::EmitTrySync(Instruction* instr, intptr_t try_index) {
+  ASSERT(is_optimizing());
+  Environment* env = instr->env();
+  CatchBlockEntryInstr* catch_block =
+      flow_graph().graph_entry()->GetCatchEntry(try_index);
+  const GrowableArray<Definition*>* idefs = catch_block->initial_definitions();
+  // Parameters.
+  intptr_t i = 0;
+  bool push_emitted = false;
+  const intptr_t num_non_copied_params = flow_graph().num_non_copied_params();
+  const intptr_t param_base =
+      kParamEndSlotFromFp + num_non_copied_params;
+  for (; i < num_non_copied_params; ++i) {
+    if ((*idefs)[i]->IsConstant()) continue;  // Common constants
+    Location loc = env->LocationAt(i);
+    Address dest(EBP, (param_base - i) * kWordSize);
+    EmitTrySyncMove(dest, loc, &push_emitted);
+  }
+
+  // Process locals. Skip exception_var and stacktrace_var.
+  CatchEntryInstr* catch_entry = catch_block->next()->AsCatchEntry();
+  intptr_t local_base = kFirstLocalSlotFromFp + num_non_copied_params;
+  intptr_t ex_idx = local_base - catch_entry->exception_var().index();
+  intptr_t st_idx = local_base - catch_entry->stacktrace_var().index();
+  for (; i < flow_graph().variable_count(); ++i) {
+    if (i == ex_idx || i == st_idx) continue;
+    if ((*idefs)[i]->IsConstant()) continue;
+    Location loc = env->LocationAt(i);
+    Address dest(EBP, (local_base - i) * kWordSize);
+    EmitTrySyncMove(dest, loc, &push_emitted);
+    // Update safepoint bitmap to indicate that the target location
+    // now contains a pointer.
+    instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
+  }
+  if (push_emitted) {
+    __ popl(EAX);
   }
 }
 
@@ -939,7 +1108,7 @@
                          0);  // No token position.
   }
   __ Comment("Enter frame");
-  __ EnterDartFrame((StackSize() * kWordSize));
+  __ EnterDartFrame(StackSize() * kWordSize);
 }
 
 
@@ -1070,6 +1239,7 @@
     AstPrinter::PrintFunctionScope(parsed_function());
   }
 
+  ASSERT(!block_order().is_empty());
   VisitBlocks();
 
   __ int3();
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 7729e57..27f6d64 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -10,6 +10,7 @@
 #include "lib/error.h"
 #include "vm/ast_printer.h"
 #include "vm/dart_entry.h"
+#include "vm/deopt_instructions.h"
 #include "vm/il_printer.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
@@ -42,6 +43,13 @@
 }
 
 
+RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+                                                 DeoptInfoBuilder* builder) {
+  UNIMPLEMENTED();  // TODO(regis): Copy ARM version.
+  return NULL;
+}
+
+
 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
                                              intptr_t stub_ix) {
   // Calls do not need stubs, they share a deoptimization trampoline.
@@ -56,6 +64,7 @@
 
   __ BranchLink(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
+  __ break_(0);  // TODO(regis): Remove breakpoint to save space.
 #undef __
 }
 
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 70074ca..2ae5235 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -10,6 +10,7 @@
 #include "lib/error.h"
 #include "vm/ast_printer.h"
 #include "vm/dart_entry.h"
+#include "vm/deopt_instructions.h"
 #include "vm/il_printer.h"
 #include "vm/locations.h"
 #include "vm/object_store.h"
@@ -43,6 +44,98 @@
 }
 
 
+RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+                                                 DeoptInfoBuilder* builder) {
+  if (deoptimization_env_ == NULL) return DeoptInfo::null();
+
+  intptr_t stack_height = compiler->StackSize();
+  AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
+
+  intptr_t slot_ix = 0;
+  Environment* current = deoptimization_env_;
+
+  // Emit all kMaterializeObject instructions describing objects to be
+  // materialized on the deoptimization as a prefix to the deoptimization info.
+  EmitMaterializations(deoptimization_env_, builder);
+
+  // The real frame starts here.
+  builder->MarkFrameStart();
+
+  // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
+
+  // Current FP and PC.
+  builder->AddCallerFp(slot_ix++);
+  builder->AddReturnAddress(current->function(),
+                            deopt_id(),
+                            slot_ix++);
+
+  // Emit all values that are needed for materialization as a part of the
+  // expression stack for the bottom-most frame. This guarantees that GC
+  // will be able to find them during materialization.
+  slot_ix = builder->EmitMaterializationArguments(slot_ix);
+
+  // For the innermost environment, set outgoing arguments and the locals.
+  for (intptr_t i = current->Length() - 1;
+       i >= current->fixed_parameter_count();
+       i--) {
+    builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
+  }
+
+  // Current PC marker and caller FP.
+  builder->AddPcMarker(current->function(), slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+
+  Environment* previous = current;
+  current = current->outer();
+  while (current != NULL) {
+    // For any outer environment the deopt id is that of the call instruction
+    // which is recorded in the outer environment.
+    builder->AddReturnAddress(current->function(),
+                              Isolate::ToDeoptAfter(current->deopt_id()),
+                              slot_ix++);
+
+    // The values of outgoing arguments can be changed from the inlined call so
+    // we must read them from the previous environment.
+    for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+      builder->AddCopy(previous->ValueAt(i),
+                       previous->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // Set the locals, note that outgoing arguments are not in the environment.
+    for (intptr_t i = current->Length() - 1;
+         i >= current->fixed_parameter_count();
+         i--) {
+      builder->AddCopy(current->ValueAt(i),
+                       current->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // PC marker and caller FP.
+    builder->AddPcMarker(current->function(), slot_ix++);
+    builder->AddCallerFp(slot_ix++);
+
+    // Iterate on the outer environment.
+    previous = current;
+    current = current->outer();
+  }
+  // The previous pointer is now the outermost environment.
+  ASSERT(previous != NULL);
+
+  // For the outermost environment, set caller PC.
+  builder->AddCallerPc(slot_ix++);
+
+  // For the outermost environment, set the incoming arguments.
+  for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+    builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
+  }
+
+  const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+  return deopt_info.raw();
+}
+
+
 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
                                              intptr_t stub_ix) {
   // Calls do not need stubs, they share a deoptimization trampoline.
@@ -642,6 +735,80 @@
                            Scanner::kDummyTokenIndex);
     }
     AllocateRegistersLocally(instr);
+  } else if (instr->MayThrow()  &&
+             (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) {
+    // Optimized try-block: Sync locals to fixed stack locations.
+    EmitTrySync(instr, CurrentTryIndex());
+  }
+}
+
+
+void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+                                        Location loc,
+                                        bool* push_emitted) {
+  if (loc.IsConstant()) {
+    if (!*push_emitted) {
+      __ pushq(RAX);
+      *push_emitted = true;
+    }
+    __ LoadObject(RAX, loc.constant());
+    __ movq(dest, RAX);
+  } else if (loc.IsRegister()) {
+    if (*push_emitted && loc.reg() == RAX) {
+      __ movq(RAX, Address(RSP, 0));
+      __ movq(dest, RAX);
+    } else {
+      __ movq(dest, loc.reg());
+    }
+  } else {
+    Address src = loc.ToStackSlotAddress();
+    if (!src.Equals(dest)) {
+      if (!*push_emitted) {
+        __ pushq(RAX);
+        *push_emitted = true;
+      }
+      __ movq(RAX, src);
+      __ movq(dest, RAX);
+    }
+  }
+}
+
+
+void FlowGraphCompiler::EmitTrySync(Instruction* instr, intptr_t try_index) {
+  ASSERT(is_optimizing());
+  Environment* env = instr->env();
+  CatchBlockEntryInstr* catch_block =
+      flow_graph().graph_entry()->GetCatchEntry(try_index);
+  const GrowableArray<Definition*>* idefs = catch_block->initial_definitions();
+  // Parameters.
+  intptr_t i = 0;
+  bool push_emitted = false;
+  const intptr_t num_non_copied_params = flow_graph().num_non_copied_params();
+  const intptr_t param_base = kParamEndSlotFromFp + num_non_copied_params;
+  for (; i < num_non_copied_params; ++i) {
+    if ((*idefs)[i]->IsConstant()) continue;  // Common constants
+    Location loc = env->LocationAt(i);
+    Address dest(RBP, (param_base - i) * kWordSize);
+    EmitTrySyncMove(dest, loc, &push_emitted);
+  }
+
+  // Process locals. Skip exception_var and stacktrace_var.
+  CatchEntryInstr* catch_entry = catch_block->next()->AsCatchEntry();
+  intptr_t local_base = kFirstLocalSlotFromFp + num_non_copied_params;
+  intptr_t ex_idx = local_base - catch_entry->exception_var().index();
+  intptr_t st_idx = local_base - catch_entry->stacktrace_var().index();
+  for (; i < flow_graph().variable_count(); ++i) {
+    if (i == ex_idx || i == st_idx) continue;
+    if ((*idefs)[i]->IsConstant()) continue;
+    Location loc = env->LocationAt(i);
+    Address dest(RBP, (local_base - i) * kWordSize);
+    EmitTrySyncMove(dest, loc, &push_emitted);
+    // Update safepoint bitmap to indicate that the target location
+    // now contains a pointer.
+    instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
+  }
+  if (push_emitted) {
+    __ popq(RAX);
   }
 }
 
@@ -937,7 +1104,7 @@
                      0);  // No token position.
   }
   __ Comment("Enter frame");
-  __ EnterDartFrame((StackSize() * kWordSize));
+  __ EnterDartFrame(StackSize() * kWordSize);
 }
 
 
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index f57251c..05fd9f0 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -413,6 +413,13 @@
                              function.ToCString(),
                              function.deoptimization_counter()));
 
+    // TODO(fschneider): Enable inlining inside try-blocks.
+    if (call_data->call->GetBlock()->try_index() !=
+        CatchClauseNode::kInvalidTryIndex) {
+      TRACE_INLINING(OS::Print("     Bailout: inside try-block\n"));
+      return false;
+    }
+
     // Abort if the inlinable bit on the function is low.
     if (!function.IsInlineable()) {
       TRACE_INLINING(OS::Print("     Bailout: not inlinable\n"));
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index d37e602..f818958 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -15,6 +15,7 @@
 #include "vm/parser.h"
 #include "vm/resolver.h"
 #include "vm/scopes.h"
+#include "vm/stack_frame.h"
 #include "vm/symbols.h"
 
 namespace dart {
@@ -37,7 +38,6 @@
 DECLARE_FLAG(bool, trace_type_check_elimination);
 
 
-
 // Optimize instance calls using ICData.
 void FlowGraphOptimizer::ApplyICData() {
   VisitBlocks();
@@ -422,7 +422,8 @@
 
 
 void FlowGraphOptimizer::SelectRepresentations() {
-  // Convervatively unbox all phis that were proven to be of type Double.
+  // Convervatively unbox all phis that were proven to be of Double,
+  // Float32x4, or Uint32x4.
   for (intptr_t i = 0; i < block_order_.length(); ++i) {
     JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
     if (join_entry != NULL) {
@@ -431,6 +432,10 @@
         ASSERT(phi != NULL);
         if (phi->Type()->ToCid() == kDoubleCid) {
           phi->set_representation(kUnboxedDouble);
+        } else if (phi->Type()->ToCid() == kFloat32x4Cid) {
+          phi->set_representation(kUnboxedFloat32x4);
+        } else if (phi->Type()->ToCid() == kUint32x4Cid) {
+          phi->set_representation(kUnboxedUint32x4);
         }
       }
     }
@@ -455,6 +460,14 @@
         InsertConversionsFor(phi);
       }
     }
+    CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry();
+    if (catch_entry != NULL) {
+      for (intptr_t i = 0;
+           i < catch_entry->initial_definitions()->length();
+           i++) {
+        InsertConversionsFor((*catch_entry->initial_definitions())[i]);
+      }
+    }
     for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
       Definition* def = it.Current()->AsDefinition();
       if (def != NULL) {
@@ -547,6 +560,10 @@
       ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid);
 }
 
+static bool HasOnlyTwoUint32x4s(const ICData& ic_data) {
+  return (ic_data.NumberOfChecks() == 1) &&
+      ICDataHasReceiverArgumentClassIds(ic_data, kUint32x4Cid, kUint32x4Cid);
+}
 
 // Returns false if the ICData contains anything other than the 4 combinations
 // of Mint and Smi for the receiver and argument classes.
@@ -674,38 +691,26 @@
                call->env(),
                Definition::kEffect);
 
-  // If both index and array are constants, then do a compile-time check.
-  // TODO(srdjan): Remove once constant propagation handles bounds checks.
-  bool skip_check = false;
-  if ((*array)->IsConstant() && (*index)->IsConstant()) {
-    const ImmutableArray& constant_array =
-        ImmutableArray::Cast((*array)->AsConstant()->value());
-    const Object& constant_index = (*index)->AsConstant()->value();
-      skip_check = constant_index.IsSmi() &&
-          (Smi::Cast(constant_index).Value() < constant_array.Length());
-  }
-  if (!skip_check) {
-    // Insert array length load and bounds check.
-    const bool is_immutable =
-        CheckArrayBoundInstr::IsFixedLengthArrayType(class_id);
-    LoadFieldInstr* length =
-        new LoadFieldInstr(new Value(*array),
-                           CheckArrayBoundInstr::LengthOffsetFor(class_id),
-                           Type::ZoneHandle(Type::SmiType()),
-                           is_immutable);
-    length->set_result_cid(kSmiCid);
-    length->set_recognized_kind(
-        LoadFieldInstr::RecognizedKindFromArrayCid(class_id));
-    InsertBefore(call, length, NULL, Definition::kValue);
+  // Insert array length load and bounds check.
+  const bool is_immutable =
+      CheckArrayBoundInstr::IsFixedLengthArrayType(class_id);
+  LoadFieldInstr* length =
+      new LoadFieldInstr(new Value(*array),
+                         CheckArrayBoundInstr::LengthOffsetFor(class_id),
+                         Type::ZoneHandle(Type::SmiType()),
+                         is_immutable);
+  length->set_result_cid(kSmiCid);
+  length->set_recognized_kind(
+      LoadFieldInstr::RecognizedKindFromArrayCid(class_id));
+  InsertBefore(call, length, NULL, Definition::kValue);
+  InsertBefore(call,
+               new CheckArrayBoundInstr(new Value(length),
+                                        new Value(*index),
+                                        class_id,
+                                        call),
+               call->env(),
+               Definition::kEffect);
 
-    InsertBefore(call,
-                 new CheckArrayBoundInstr(new Value(length),
-                                          new Value(*index),
-                                          class_id,
-                                          call),
-                 call->env(),
-                 Definition::kEffect);
-  }
   if (class_id == kGrowableObjectArrayCid) {
     // Insert data elements load.
     LoadFieldInstr* elements =
@@ -1025,6 +1030,8 @@
         operands_type = kSmiCid;
       } else if (HasTwoMintOrSmi(ic_data)) {
         operands_type = kMintCid;
+      } else if (HasOnlyTwoUint32x4s(ic_data)) {
+        operands_type = kUint32x4Cid;
       } else {
         return false;
       }
@@ -1111,8 +1118,28 @@
     // Replace call.
     BinaryFloat32x4OpInstr* float32x4_bin_op =
         new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right),
-                                   call);
+                                   call->deopt_id());
     ReplaceCall(call, float32x4_bin_op);
+  } else if (operands_type == kUint32x4Cid) {
+    // Type check left.
+    AddCheckClass(left,
+                  ICData::ZoneHandle(
+                      call->ic_data()->AsUnaryClassChecksForArgNr(0)),
+                  call->deopt_id(),
+                  call->env(),
+                  call);
+    // Type check right.
+    AddCheckClass(right,
+                  ICData::ZoneHandle(
+                      call->ic_data()->AsUnaryClassChecksForArgNr(1)),
+                  call->deopt_id(),
+                  call->env(),
+                  call);
+    // Replace call.
+    BinaryUint32x4OpInstr* uint32x4_bin_op =
+        new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right),
+                                  call->deopt_id());
+    ReplaceCall(call, uint32x4_bin_op);
   } else if (op_kind == Token::kMOD) {
     // TODO(vegorov): implement fast path code for modulo.
     ASSERT(operands_type == kSmiCid);
@@ -1377,6 +1404,12 @@
 }
 
 
+void FlowGraphOptimizer::InlineObjectCid(InstanceCallInstr* call) {
+  LoadClassIdInstr* load = new LoadClassIdInstr(new Value(call->ArgumentAt(0)));
+  ReplaceCall(call, load);
+}
+
+
 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) {
   switch (kind) {
     case MethodRecognizer::kObjectArrayLength:
@@ -1407,7 +1440,24 @@
   Float32x4ShuffleInstr* instr = new Float32x4ShuffleInstr(
       getter,
       new Value(call->ArgumentAt(0)),
-      call);
+      call->deopt_id());
+  ReplaceCall(call, instr);
+  return true;
+}
+
+
+bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call,
+                                              MethodRecognizer::Kind getter) {
+  AddCheckClass(call->ArgumentAt(0),
+                ICData::ZoneHandle(
+                    call->ic_data()->AsUnaryClassChecksForArgNr(0)),
+                call->deopt_id(),
+                call->env(),
+                call);
+  Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr(
+      getter,
+      new Value(call->ArgumentAt(0)),
+      call->deopt_id());
   ReplaceCall(call, instr);
   return true;
 }
@@ -1439,6 +1489,10 @@
 
   // VM objects length getter.
   switch (recognized_kind) {
+    case MethodRecognizer::kObjectCid: {
+      InlineObjectCid(call);
+      return true;
+    }
     case MethodRecognizer::kObjectArrayLength:
     case MethodRecognizer::kImmutableArrayLength:
     case MethodRecognizer::kTypedDataLength:
@@ -1487,6 +1541,16 @@
         return false;
       }
       return InlineFloat32x4Getter(call, recognized_kind);
+    case MethodRecognizer::kUint32x4GetFlagX:
+    case MethodRecognizer::kUint32x4GetFlagY:
+    case MethodRecognizer::kUint32x4GetFlagZ:
+    case MethodRecognizer::kUint32x4GetFlagW: {
+      if (!ic_data.HasReceiverClassId(kUint32x4Cid) ||
+          !ic_data.HasOneTarget()) {
+        return false;
+      }
+      return InlineUint32x4Getter(call, recognized_kind);
+    }
     default:
       ASSERT(recognized_kind == MethodRecognizer::kUnknown);
   }
@@ -1754,6 +1818,10 @@
   if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
     return TryInlineFloat32x4Method(call, recognized_kind);
   }
+
+  if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
+    return TryInlineUint32x4Method(call, recognized_kind);
+  }
   return false;
 }
 
@@ -1781,7 +1849,7 @@
       // Replace call.
       Float32x4ComparisonInstr* cmp =
           new Float32x4ComparisonInstr(recognized_kind, new Value(left),
-                                       new Value(right), call);
+                                       new Value(right), call->deopt_id());
       ReplaceCall(call, cmp);
       return true;
     }
@@ -1798,7 +1866,7 @@
                     call);
       Float32x4MinMaxInstr* minmax =
           new Float32x4MinMaxInstr(recognized_kind, new Value(left),
-                                   new Value(right), call);
+                                   new Value(right), call->deopt_id());
       ReplaceCall(call, minmax);
       return true;
     }
@@ -1817,7 +1885,7 @@
       // register and can be destroyed.
       Float32x4ScaleInstr* scale =
           new Float32x4ScaleInstr(recognized_kind, new Value(right),
-                                  new Value(left), call);
+                                  new Value(left), call->deopt_id());
       ReplaceCall(call, scale);
       return true;
     }
@@ -1832,7 +1900,8 @@
                     call->env(),
                     call);
       Float32x4SqrtInstr* sqrt =
-          new Float32x4SqrtInstr(recognized_kind, new Value(left), call);
+          new Float32x4SqrtInstr(recognized_kind, new Value(left),
+                                 call->deopt_id());
       ReplaceCall(call, sqrt);
       return true;
     }
@@ -1852,7 +1921,7 @@
       Float32x4WithInstr* with = new Float32x4WithInstr(recognized_kind,
                                                         new Value(left),
                                                         new Value(right),
-                                                        call);
+                                                        call->deopt_id());
       ReplaceCall(call, with);
       return true;
     }
@@ -1867,7 +1936,8 @@
                     call->env(),
                     call);
       Float32x4ZeroArgInstr* zeroArg =
-          new Float32x4ZeroArgInstr(recognized_kind, new Value(left), call);
+          new Float32x4ZeroArgInstr(recognized_kind, new Value(left),
+                                    call->deopt_id());
       ReplaceCall(call, zeroArg);
       return true;
     }
@@ -1885,7 +1955,7 @@
       Float32x4ClampInstr* clamp = new Float32x4ClampInstr(new Value(left),
                                                            new Value(lower),
                                                            new Value(upper),
-                                                           call);
+                                                           call->deopt_id());
       ReplaceCall(call, clamp);
       return true;
     }
@@ -1899,7 +1969,7 @@
                     call->env(),
                     call);
       Float32x4ToUint32x4Instr* cast =
-          new Float32x4ToUint32x4Instr(new Value(left), call);
+          new Float32x4ToUint32x4Instr(new Value(left), call->deopt_id());
       ReplaceCall(call, cast);
       return true;
     }
@@ -1909,6 +1979,71 @@
 }
 
 
+bool FlowGraphOptimizer::TryInlineUint32x4Method(
+    InstanceCallInstr* call,
+    MethodRecognizer::Kind recognized_kind) {
+  ASSERT(call->HasICData());
+  switch (recognized_kind) {
+    case MethodRecognizer::kUint32x4Select: {
+      Definition* mask = call->ArgumentAt(0);
+      Definition* trueValue = call->ArgumentAt(1);
+      Definition* falseValue = call->ArgumentAt(2);
+      // Type check left.
+      AddCheckClass(mask,
+                    ICData::ZoneHandle(
+                        call->ic_data()->AsUnaryClassChecksForArgNr(0)),
+                    call->deopt_id(),
+                    call->env(),
+                    call);
+      Uint32x4SelectInstr* select = new Uint32x4SelectInstr(
+          new Value(mask),
+          new Value(trueValue),
+          new Value(falseValue),
+          call->deopt_id());
+      ReplaceCall(call, select);
+      return true;
+    }
+    case MethodRecognizer::kUint32x4ToUint32x4: {
+      Definition* left = call->ArgumentAt(0);
+      // Type check left.
+      AddCheckClass(left,
+                    ICData::ZoneHandle(
+                        call->ic_data()->AsUnaryClassChecksForArgNr(0)),
+                    call->deopt_id(),
+                    call->env(),
+                    call);
+      Uint32x4ToFloat32x4Instr* cast =
+          new Uint32x4ToFloat32x4Instr(new Value(left), call->deopt_id());
+      ReplaceCall(call, cast);
+      return true;
+    }
+    case MethodRecognizer::kUint32x4WithFlagX:
+    case MethodRecognizer::kUint32x4WithFlagY:
+    case MethodRecognizer::kUint32x4WithFlagZ:
+    case MethodRecognizer::kUint32x4WithFlagW: {
+      Definition* left = call->ArgumentAt(0);
+      Definition* flag = call->ArgumentAt(1);
+      // Type check left.
+      AddCheckClass(left,
+                    ICData::ZoneHandle(
+                        call->ic_data()->AsUnaryClassChecksForArgNr(0)),
+                    call->deopt_id(),
+                    call->env(),
+                    call);
+      Uint32x4SetFlagInstr* setFlag = new Uint32x4SetFlagInstr(
+          recognized_kind,
+          new Value(left),
+          new Value(flag),
+          call->deopt_id());
+      ReplaceCall(call, setFlag);
+      return true;
+    }
+    default:
+      return false;
+  }
+}
+
+
 bool FlowGraphOptimizer::BuildByteArrayViewLoad(
     InstanceCallInstr* call,
     intptr_t receiver_cid,
@@ -2288,11 +2423,12 @@
         new MathSqrtInstr(new Value(call->ArgumentAt(0)), call);
     ReplaceCall(call, sqrt);
   } else if (recognized_kind == MethodRecognizer::kFloat32x4Zero) {
-    Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call);
+    Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call->deopt_id());
     ReplaceCall(call, zero);
   } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) {
     Float32x4SplatInstr* splat =
-        new Float32x4SplatInstr(new Value(call->ArgumentAt(1)), call);
+        new Float32x4SplatInstr(new Value(call->ArgumentAt(1)),
+                                call->deopt_id());
     ReplaceCall(call, splat);
   } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) {
     Float32x4ConstructorInstr* con =
@@ -2300,7 +2436,15 @@
                                       new Value(call->ArgumentAt(2)),
                                       new Value(call->ArgumentAt(3)),
                                       new Value(call->ArgumentAt(4)),
-                                      call);
+                                      call->deopt_id());
+    ReplaceCall(call, con);
+  } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) {
+    Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr(
+        new Value(call->ArgumentAt(1)),
+        new Value(call->ArgumentAt(2)),
+        new Value(call->ArgumentAt(3)),
+        new Value(call->ArgumentAt(4)),
+        call->deopt_id());
     ReplaceCall(call, con);
   }
 }
@@ -2710,6 +2854,30 @@
        !block_it.Done();
        block_it.Advance()) {
     BlockEntryInstr* block = block_it.Current();
+
+
+    if (block->IsGraphEntry() || block->IsCatchBlockEntry()) {
+      const GrowableArray<Definition*>& initial = block->IsGraphEntry()
+          ? *block->AsGraphEntry()->initial_definitions()
+          : *block->AsCatchBlockEntry()->initial_definitions();
+      for (intptr_t i = 0; i < initial.length(); ++i) {
+        Definition* current = initial[i];
+        if (current->Type()->ToCid() == kSmiCid) {
+          smi_values_.Add(current);
+        }
+      }
+    }
+
+    JoinEntryInstr* join = block->AsJoinEntry();
+    if (join != NULL) {
+      for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
+        PhiInstr* current = phi_it.Current();
+        if (current->Type()->ToCid() == kSmiCid) {
+          smi_values_.Add(current);
+        }
+      }
+    }
+
     for (ForwardInstructionIterator instr_it(block);
          !instr_it.Done();
          instr_it.Advance()) {
@@ -2724,16 +2892,6 @@
         smi_checks_.Add(current->AsCheckSmi());
       }
     }
-
-    JoinEntryInstr* join = block->AsJoinEntry();
-    if (join != NULL) {
-      for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
-        PhiInstr* current = phi_it.Current();
-        if (current->Type()->ToCid() == kSmiCid) {
-          smi_values_.Add(current);
-        }
-      }
-    }
   }
 }
 
@@ -3171,6 +3329,73 @@
 }
 
 
+void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) {
+  // For every catch-block: Iterate over all call instructions inside the
+  // corresponding try-block and figure out for each environment value if it
+  // is the same constant at all calls. If yes, replace the initial definition
+  // at the catch-entry with this constant.
+  const GrowableArray<CatchBlockEntryInstr*>& catch_entries =
+      flow_graph->graph_entry()->catch_entries();
+  intptr_t base = kFirstLocalSlotFromFp + flow_graph->num_non_copied_params();
+  for (intptr_t catch_idx = 0;
+       catch_idx < catch_entries.length();
+       ++catch_idx) {
+    CatchBlockEntryInstr* cb = catch_entries[catch_idx];
+    CatchEntryInstr* catch_entry = cb->next()->AsCatchEntry();
+
+    // Initialize cdefs with the original initial definitions (ParameterInstr).
+    // The following representation is used:
+    // ParameterInstr => unknown
+    // ConstantInstr => known constant
+    // NULL => non-constant
+    GrowableArray<Definition*>* idefs = cb->initial_definitions();
+    GrowableArray<Definition*> cdefs(idefs->length());
+    cdefs.AddArray(*idefs);
+
+    // exception_var and stacktrace_var are never constant.
+    intptr_t ex_idx = base - catch_entry->exception_var().index();
+    intptr_t st_idx = base - catch_entry->stacktrace_var().index();
+    cdefs[ex_idx] = cdefs[st_idx] = NULL;
+
+    for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
+         !block_it.Done();
+         block_it.Advance()) {
+      BlockEntryInstr* block = block_it.Current();
+      if (block->try_index() == cb->catch_try_index()) {
+        for (ForwardInstructionIterator instr_it(block);
+             !instr_it.Done();
+             instr_it.Advance()) {
+          Instruction* current = instr_it.Current();
+          if (current->MayThrow()) {
+            Environment* env = current->env();
+            for (intptr_t env_idx = 0; env_idx < cdefs.length(); ++env_idx) {
+              if (cdefs[env_idx] != NULL &&
+                  env->ValueAt(env_idx)->BindsToConstant()) {
+                cdefs[env_idx] = env->ValueAt(env_idx)->definition();
+              }
+              if (cdefs[env_idx] != env->ValueAt(env_idx)->definition()) {
+                cdefs[env_idx] = NULL;
+              }
+            }
+          }
+        }
+      }
+    }
+    for (intptr_t j = 0; j < idefs->length(); ++j) {
+      if (cdefs[j] != NULL && cdefs[j]->IsConstant()) {
+        // TODO(fschneider): Use constants from the constant pool.
+        Definition* old = (*idefs)[j];
+        ConstantInstr* orig = cdefs[j]->AsConstant();
+        ConstantInstr* copy = new ConstantInstr(orig->value());
+        copy->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index());
+        old->ReplaceUsesWith(copy);
+        (*idefs)[j] = copy;
+      }
+    }
+  }
+}
+
+
 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) {
   for (intptr_t j = 0; j < header->PredecessorCount(); ++j) {
     BlockEntryInstr* candidate = header->PredecessorAt(j);
@@ -3256,9 +3481,24 @@
 }
 
 
+static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets,
+                                intptr_t loop_header_index,
+                                Instruction* instr) {
+  return (sets != NULL) &&
+      instr->HasExprId() &&
+      ((*sets)[loop_header_index] != NULL) &&
+      (*sets)[loop_header_index]->Contains(instr->expr_id());
+}
+
+
 void LICM::Optimize() {
-  GrowableArray<BlockEntryInstr*> loop_headers;
-  flow_graph()->ComputeLoops(&loop_headers);
+  const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
+      flow_graph()->loop_headers();
+
+  ZoneGrowableArray<BitVector*>* loop_invariant_loads =
+      flow_graph()->loop_invariant_loads();
+
+  BlockEffects* block_effects = flow_graph()->block_effects();
 
   for (intptr_t i = 0; i < loop_headers.length(); ++i) {
     BlockEntryInstr* header = loop_headers[i];
@@ -3274,8 +3514,9 @@
            !it.Done();
            it.Advance()) {
         Instruction* current = it.Current();
-        if (current->AllowsCSE() &&
-            flow_graph()->block_effects()->CanBeMovedTo(current, pre_header)) {
+        if ((current->AllowsCSE() &&
+             block_effects->CanBeMovedTo(current, pre_header)) ||
+             IsLoopInvariantLoad(loop_invariant_loads, i, current)) {
           bool inputs_loop_invariant = true;
           for (int i = 0; i < current->InputCount(); ++i) {
             Definition* input_def = current->InputAt(i)->definition();
@@ -3801,6 +4042,12 @@
       } else {
         defn->set_expr_id(result->expr_id());
       }
+
+      if (FLAG_trace_optimization) {
+        OS::Print("load v%"Pd" is numbered as %"Pd"\n",
+                  defn->ssa_temp_index(),
+                  defn->expr_id());
+      }
     }
   }
 
@@ -3866,6 +4113,9 @@
   bool Optimize() {
     ComputeInitialSets();
     ComputeOutValues();
+    if (graph_->is_licm_allowed()) {
+      MarkLoopInvariantLoads();
+    }
     ForwardLoads();
     EmitPhis();
     return forwarded_;
@@ -4121,6 +4371,50 @@
     }
   }
 
+  void MarkLoopInvariantLoads() {
+    const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
+        graph_->loop_headers();
+
+    ZoneGrowableArray<BitVector*>* invariant_loads =
+        new ZoneGrowableArray<BitVector*>(loop_headers.length());
+
+    for (intptr_t i = 0; i < loop_headers.length(); i++) {
+      BlockEntryInstr* header = loop_headers[i];
+      BlockEntryInstr* pre_header = FindPreHeader(header);
+      if (pre_header == NULL) {
+        invariant_loads->Add(NULL);
+        continue;
+      }
+
+      BitVector* loop_gen = new BitVector(aliased_set_->max_expr_id());
+      for (BitVector::Iterator loop_it(header->loop_info());
+           !loop_it.Done();
+           loop_it.Advance()) {
+        const intptr_t preorder_number = loop_it.Current();
+        loop_gen->AddAll(gen_[preorder_number]);
+      }
+
+      for (BitVector::Iterator loop_it(header->loop_info());
+           !loop_it.Done();
+           loop_it.Advance()) {
+        const intptr_t preorder_number = loop_it.Current();
+        loop_gen->RemoveAll(kill_[preorder_number]);
+      }
+
+      if (FLAG_trace_optimization) {
+        for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) {
+          OS::Print("load %"Pd" is loop invariant for B%"Pd"\n",
+                    it.Current(),
+                    header->block_id());
+        }
+      }
+
+      invariant_loads->Add(loop_gen);
+    }
+
+    graph_->set_loop_invariant_loads(invariant_loads);
+  }
+
   // Compute incoming value for the given expression id.
   // Will create a phi if different values are incoming from multiple
   // predecessors.
@@ -4444,8 +4738,8 @@
     const GrowableArray<BlockEntryInstr*>& ignored)
     : FlowGraphVisitor(ignored),
       graph_(graph),
-      unknown_(Object::transition_sentinel()),
-      non_constant_(Object::sentinel()),
+      unknown_(Object::unknown_constant()),
+      non_constant_(Object::non_constant()),
       reachable_(new BitVector(graph->preorder().length())),
       definition_marks_(new BitVector(graph->max_virtual_register_number())),
       block_worklist_(),
@@ -4530,7 +4824,11 @@
   }
   ASSERT(ForwardInstructionIterator(block).Done());
 
-  SetReachable(block->normal_entry());
+  // TODO(fschneider): Improve this approximation. The catch entry is only
+  // reachable if a call in the try-block is reachable.
+  for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
+    SetReachable(block->SuccessorAt(i));
+  }
 }
 
 
@@ -4550,6 +4848,10 @@
 
 
 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
+  const GrowableArray<Definition*>& defs = *block->initial_definitions();
+  for (intptr_t i = 0; i < defs.length(); ++i) {
+    defs[i]->Accept(this);
+  }
   for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
     it.Current()->Accept(this);
   }
@@ -4882,6 +5184,15 @@
 
 
 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) {
+  const Field& field = instr->field();
+  ASSERT(field.is_static());
+  if (field.is_final()) {
+    Instance& obj = Instance::Handle(field.value());
+    if (obj.IsSmi() || obj.IsOld()) {
+      SetValue(instr, obj);
+      return;
+    }
+  }
   SetValue(instr, non_constant_);
 }
 
@@ -5259,6 +5570,38 @@
 }
 
 
+void ConstantPropagator::VisitUint32x4BoolConstructor(
+    Uint32x4BoolConstructorInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitUint32x4GetFlag(Uint32x4GetFlagInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitUint32x4SetFlag(Uint32x4SetFlagInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitUint32x4Select(Uint32x4SelectInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitUint32x4ToFloat32x4(
+    Uint32x4ToFloat32x4Instr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitBinaryUint32x4Op(BinaryUint32x4OpInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) {
   const Object& value = instr->value()->definition()->constant_value();
   if (IsNonConstant(value)) {
@@ -5362,12 +5705,18 @@
 void ConstantPropagator::VisitBranches() {
   GraphEntryInstr* entry = graph_->graph_entry();
   reachable_->Add(entry->preorder_number());
-  // TODO(fschneider): Handle CatchEntry.
-  reachable_->Add(entry->normal_entry()->preorder_number());
-  block_worklist_.Add(entry->normal_entry());
+  block_worklist_.Add(entry);
 
   while (!block_worklist_.is_empty()) {
     BlockEntryInstr* block = block_worklist_.RemoveLast();
+    if (block->IsGraphEntry()) {
+      // TODO(fschneider): Improve this approximation. Catch entries are only
+      // reachable if a call in the corresponding try-block is reachable.
+      for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
+        SetReachable(block->SuccessorAt(i));
+      }
+      continue;
+    }
     Instruction* last = block->last_instruction();
     if (last->IsGoto()) {
       SetReachable(last->AsGoto()->successor());
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 46111e9..18b4eec 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -44,6 +44,8 @@
 
   void InferSmiRanges();
 
+  void AnalyzeTryCatch();
+
   // Remove environments from the instructions which do not deoptimize.
   void EliminateEnvironments();
 
@@ -87,6 +89,8 @@
   bool TryInlineInstanceMethod(InstanceCallInstr* call);
   bool TryInlineFloat32x4Method(InstanceCallInstr* call,
                                 MethodRecognizer::Kind recognized_kind);
+  bool TryInlineUint32x4Method(InstanceCallInstr* call,
+                               MethodRecognizer::Kind recognized_kind);
   void ReplaceWithInstanceOf(InstanceCallInstr* instr);
   void ReplaceWithTypeCast(InstanceCallInstr* instr);
 
@@ -140,6 +144,8 @@
 
   bool InlineFloat32x4Getter(InstanceCallInstr* call,
                              MethodRecognizer::Kind getter);
+  bool InlineUint32x4Getter(InstanceCallInstr* call,
+                            MethodRecognizer::Kind getter);
 
   void InlineImplicitInstanceGetter(InstanceCallInstr* call);
   void InlineArrayLengthGetter(InstanceCallInstr* call,
@@ -149,6 +155,7 @@
   void InlineGrowableArrayCapacityGetter(InstanceCallInstr* call);
   void InlineStringLengthGetter(InstanceCallInstr* call);
   void InlineStringIsEmptyGetter(InstanceCallInstr* call);
+  void InlineObjectCid(InstanceCallInstr* call);
 
   RawBool* InstanceOfAsBool(const ICData& ic_data,
                             const AbstractType& type) const;
@@ -236,7 +243,7 @@
   static void OptimizeBranches(FlowGraph* graph);
 
   // Used to initialize the abstract value of definitions.
-  static RawObject* Unknown() { return Object::transition_sentinel().raw(); }
+  static RawObject* Unknown() { return Object::unknown_constant().raw(); }
 
  private:
   void Analyze();
@@ -345,6 +352,14 @@
   GrowableArray<MaterializeObjectInstr*> materializations_;
 };
 
+
+// Optimize spill stores inside try-blocks by identifying values that always
+// contain a single known constant at catch block entry.
+class TryCatchAnalyzer : public AllStatic {
+ public:
+  static void Optimize(FlowGraph* flow_graph);
+};
+
 }  // namespace dart
 
 #endif  // VM_FLOW_GRAPH_OPTIMIZER_H_
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 9cc0858..f709124 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -473,6 +473,20 @@
 }
 
 
+// Return true if the class is private to our internal libraries (not extendable
+// or implementable by users).
+// (TODO): Allow more libraries.
+static bool IsKnownPrivateClass(const Class& type_class) {
+  if (!Library::IsPrivate(String::Handle(type_class.Name()))) return false;
+  const Library& library = Library::Handle(type_class.library());
+  if (library.raw() == Library::CoreLibrary()) return true;
+  if (library.raw() == Library::CollectionLibrary()) return true;
+  if (library.raw() == Library::TypedDataLibrary()) return true;
+  if (library.raw() == Library::MathLibrary()) return true;
+  return false;
+}
+
+
 intptr_t CompileType::ToNullableCid() {
   if (cid_ == kIllegalCid) {
     ASSERT(type_ != NULL);
@@ -481,11 +495,16 @@
       cid_ = kDynamicCid;
     } else if (type_->IsVoidType()) {
       cid_ = kNullCid;
-    } else if (FLAG_use_cha && type_->HasResolvedTypeClass()) {
+    } else if (type_->HasResolvedTypeClass()) {
       const Class& type_class = Class::Handle(type_->type_class());
-      if (!type_class.is_implemented() &&
-          !CHA::HasSubclasses(type_class.id())) {
-        cid_ = type_class.id();
+      if (FLAG_use_cha || IsKnownPrivateClass(type_class)) {
+        // A known private class cannot be subclassed or implemented.
+        if (!type_class.is_implemented() &&
+            !CHA::HasSubclasses(type_class.id())) {
+          cid_ = type_class.id();
+        } else {
+          cid_ = kDynamicCid;
+        }
       } else {
         cid_ = kDynamicCid;
       }
@@ -668,8 +687,12 @@
   // always be wrongly eliminated.
   // However there are parameters that are known to match their declared type:
   // for example receiver and construction phase.
-  const Function& function = block_->parsed_function().function();
-  LocalScope* scope = block_->parsed_function().node_sequence()->scope();
+  GraphEntryInstr* graph_entry = block_->AsGraphEntry();
+  // Parameters at catch-blocks have type dynamic.
+  if (graph_entry == NULL) return CompileType::Dynamic();
+
+  const Function& function = graph_entry->parsed_function().function();
+  LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope();
   const AbstractType& type = scope->VariableAt(index())->type();
 
   // Parameter is the constructor phase.
@@ -1046,6 +1069,35 @@
 }
 
 
+CompileType Uint32x4BoolConstructorInstr::ComputeType() const {
+  return CompileType::FromCid(kUint32x4Cid);
+}
+
+CompileType Uint32x4GetFlagInstr::ComputeType() const {
+  return CompileType::FromCid(kBoolCid);
+}
+
+
+CompileType Uint32x4SelectInstr::ComputeType() const {
+  return CompileType::FromCid(kFloat32x4Cid);
+}
+
+
+CompileType Uint32x4SetFlagInstr::ComputeType() const {
+  return CompileType::FromCid(kUint32x4Cid);
+}
+
+
+CompileType Uint32x4ToFloat32x4Instr::ComputeType() const {
+  return CompileType::FromCid(kFloat32x4Cid);
+}
+
+
+CompileType BinaryUint32x4OpInstr::ComputeType() const {
+  return CompileType::FromCid(kUint32x4Cid);
+}
+
+
 CompileType MathSqrtInstr::ComputeType() const {
   return CompileType::FromCid(kDoubleCid);
 }
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index ebac00a..f7aa016 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -700,6 +700,57 @@
 }
 
 
+void Uint32x4BoolConstructorInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("Uint32x4.bool(");
+  value0()->PrintTo(f);
+  f->Print(", ");
+  value1()->PrintTo(f);
+  f->Print(", ");
+  value2()->PrintTo(f);
+  f->Print(", ");
+  value3()->PrintTo(f);
+  f->Print(")");
+}
+
+
+void Uint32x4GetFlagInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("Uint32x4.%s ", MethodRecognizer::KindToCString(op_kind()));
+  value()->PrintTo(f);
+}
+
+
+void Uint32x4SetFlagInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("Uint32x4.%s ", MethodRecognizer::KindToCString(op_kind()));
+  value()->PrintTo(f);
+  f->Print(", ");
+  flagValue()->PrintTo(f);
+}
+
+
+void Uint32x4SelectInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("Uint32x4.select ");
+  mask()->PrintTo(f);
+  f->Print(", ");
+  trueValue()->PrintTo(f);
+  f->Print(", ");
+  falseValue()->PrintTo(f);
+}
+
+
+void Uint32x4ToFloat32x4Instr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("Uint32x4.toFloat32x4 ");
+  left()->PrintTo(f);
+}
+
+
+void BinaryUint32x4OpInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("%s, ", Token::Str(op_kind()));
+  left()->PrintTo(f);
+  f->Print(", ");
+  right()->PrintTo(f);
+}
+
+
 void BinaryMintOpInstr::PrintOperandsTo(BufferFormatter* f) const {
   f->Print("%s, ", Token::Str(op_kind()));
   left()->PrintTo(f);
@@ -824,6 +875,17 @@
     f->Print(" ");
     parallel_move()->PrintTo(f);
   }
+
+  const GrowableArray<Definition*>& defns = initial_definitions_;
+  if (defns.length() > 0) {
+    f->Print(" {");
+    for (intptr_t i = 0; i < defns.length(); ++i) {
+      Definition* def = defns[i];
+      f->Print("\n      ");
+      def->PrintTo(f);
+    }
+    f->Print("\n}");
+  }
 }
 
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index daa9d96..91eca39 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -228,7 +228,8 @@
       normal_entry_(normal_entry),
       catch_entries_(),
       initial_definitions_(),
-      spill_slot_count_(0) {
+      spill_slot_count_(0),
+      fixed_slot_count_(0) {
 }
 
 
@@ -243,6 +244,16 @@
 }
 
 
+CatchBlockEntryInstr* GraphEntryInstr::GetCatchEntry(intptr_t index) {
+  // TODO(fschneider): Sort the catch entries by catch_try_index to avoid
+  // searching.
+  for (intptr_t i = 0; i < catch_entries_.length(); ++i) {
+    if (catch_entries_[i]->catch_try_index() == index) return catch_entries_[i];
+  }
+  return NULL;
+}
+
+
 static bool StartsWith(const String& name, const char* prefix, intptr_t n) {
   ASSERT(name.IsOneByteString());
 
@@ -2300,15 +2311,21 @@
   Range* index_range = index()->definition()->range();
 
   // Range of the index is unknown can't decide if the check is redundant.
-  if (index_range == NULL) return false;
+  if (index_range == NULL) {
+    return false;
+  }
 
   // Range of the index is not positive. Check can't be redundant.
-  if (Range::ConstantMin(index_range).value() < 0) return false;
+  if (Range::ConstantMin(index_range).value() < 0) {
+    return false;
+  }
 
   RangeBoundary max = CanonicalizeBoundary(index_range->max(),
                                            RangeBoundary::OverflowedMaxSmi());
 
-  if (max.Overflowed()) return false;
+  if (max.Overflowed()) {
+    return false;
+  }
 
   // Try to compare constant boundaries.
   if (max.UpperBound().value() < length.LowerBound().value()) {
@@ -2316,7 +2333,9 @@
   }
 
   length = CanonicalizeBoundary(length, RangeBoundary::OverflowedMaxSmi());
-  if (length.Overflowed()) return false;
+  if (length.Overflowed()) {
+    return false;
+  }
 
   // Try symbolic comparison.
   do {
@@ -2328,6 +2347,12 @@
 }
 
 
+Instruction* CheckArrayBoundInstr::Canonicalize(FlowGraph* flow_graph) {
+  return IsRedundant(RangeBoundary::FromDefinition(length()->definition())) ?
+      NULL : this;
+}
+
+
 intptr_t CheckArrayBoundInstr::LengthOffsetFor(intptr_t class_id) {
   if (RawObject::IsExternalTypedDataClassId(class_id)) {
     return ExternalTypedData::length_offset();
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 18e2ab3..f881959 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -35,6 +35,7 @@
 // (class-name, function-name, recognized enum, fingerprint).
 // See intrinsifier for fingerprint computation.
 #define RECOGNIZED_LIST(V)                                                     \
+  V(Object, get:_cid, ObjectCid, 732498573)                                    \
   V(_ObjectArray, get:length, ObjectArrayLength, 405297088)                    \
   V(_ImmutableArray, get:length, ImmutableArrayLength, 433698233)              \
   V(_TypedList, get:length, TypedDataLength, 1004567191)                       \
@@ -103,6 +104,17 @@
   V(_Float32x4, withZ, Float32x4WithZ, 219466242)                              \
   V(_Float32x4, withW, Float32x4WithW, 219466242)                              \
   V(_Float32x4, _toUint32x4, Float32x4ToUint32x4, 1044409108)                  \
+  V(Uint32x4, Uint32x4.bool, Uint32x4BoolConstructor, 1489869343)              \
+  V(_Uint32x4, get:flagX, Uint32x4GetFlagX, 782547529)                         \
+  V(_Uint32x4, get:flagY, Uint32x4GetFlagY, 782547529)                         \
+  V(_Uint32x4, get:flagZ, Uint32x4GetFlagZ, 782547529)                         \
+  V(_Uint32x4, get:flagW, Uint32x4GetFlagW, 782547529)                         \
+  V(_Uint32x4, select, Uint32x4Select, 405662786)                              \
+  V(_Uint32x4, withFlagX, Uint32x4WithFlagX, 980864994)                        \
+  V(_Uint32x4, withFlagY, Uint32x4WithFlagY, 980864994)                        \
+  V(_Uint32x4, withFlagZ, Uint32x4WithFlagZ, 980864994)                        \
+  V(_Uint32x4, withFlagW, Uint32x4WithFlagW, 980864994)                        \
+  V(_Uint32x4, _toFloat32x4, Uint32x4ToUint32x4, 311564070)                    \
 
 
 // Class that recognizes the name and owner of a function and returns the
@@ -588,6 +600,13 @@
   M(Float32x4With)                                                             \
   M(Float32x4ToUint32x4)                                                       \
   M(MaterializeObject)                                                         \
+  M(Uint32x4BoolConstructor)                                                   \
+  M(Uint32x4GetFlag)                                                           \
+  M(Uint32x4Select)                                                            \
+  M(Uint32x4SetFlag)                                                           \
+  M(Uint32x4ToFloat32x4)                                                       \
+  M(BinaryUint32x4Op)                                                          \
+
 
 #define FORWARD_DECLARATION(type) class type##Instr;
 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
@@ -618,7 +637,7 @@
         previous_(NULL),
         next_(NULL),
         env_(NULL),
-        expr_id_(-1) { }
+        expr_id_(kNoExprId) { }
 
   virtual Tag tag() const = 0;
 
@@ -794,9 +813,11 @@
   // Get the block entry for this instruction.
   virtual BlockEntryInstr* GetBlock() const;
 
-  // Id for instructions used in CSE.
+  // Id for load instructions used during load forwarding pass and later in
+  // LICM.
   intptr_t expr_id() const { return expr_id_; }
   void set_expr_id(intptr_t expr_id) { expr_id_ = expr_id; }
+  bool HasExprId() const { return expr_id_ != kNoExprId; }
 
   // Returns a hash code for use with hash maps.
   virtual intptr_t Hashcode() const;
@@ -827,6 +848,8 @@
 
   void InheritDeoptTargetAfter(Instruction* other);
 
+  virtual bool MayThrow() const = 0;
+
  protected:
   // Fetch deopt id without checking if this computation can deoptimize.
   intptr_t GetDeoptId() const {
@@ -855,6 +878,12 @@
   friend class Float32x4ClampInstr;
   friend class Float32x4WithInstr;
   friend class Float32x4ToUint32x4Instr;
+  friend class Uint32x4BoolConstructorInstr;
+  friend class Uint32x4GetFlagInstr;
+  friend class Uint32x4SetFlagInstr;
+  friend class Uint32x4SelectInstr;
+  friend class Uint32x4ToFloat32x4Instr;
+  friend class BinaryUint32x4OpInstr;
   friend class BinaryMintOpInstr;
   friend class BinarySmiOpInstr;
   friend class UnarySmiOpInstr;
@@ -886,6 +915,10 @@
 
   virtual void RawSetInputAt(intptr_t i, Value* value) = 0;
 
+  enum {
+    kNoExprId = -1
+  };
+
   intptr_t deopt_id_;
   intptr_t lifetime_position_;  // Position used by register allocator.
   Instruction* previous_;
@@ -1017,6 +1050,8 @@
 
   virtual void PrintTo(BufferFormatter* f) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   GrowableArray<MoveOperands*> moves_;   // Elements cannot be null.
 
@@ -1122,8 +1157,15 @@
   virtual EffectSet Effects() const { return EffectSet::None(); }
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
   intptr_t try_index() const { return try_index_; }
 
+  // True for blocks inside a try { } region.
+  bool InsideTryBlock() const {
+    return try_index_ != CatchClauseNode::kInvalidTryIndex;
+  }
+
   BitVector* loop_info() const { return loop_info_; }
   void set_loop_info(BitVector* loop_info) {
     loop_info_ = loop_info;
@@ -1248,6 +1290,8 @@
 
   void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); }
 
+  CatchBlockEntryInstr* GetCatchEntry(intptr_t index);
+
   virtual void PrepareEntry(FlowGraphCompiler* compiler);
 
   GrowableArray<Definition*>* initial_definitions() {
@@ -1261,12 +1305,24 @@
     spill_slot_count_ = count;
   }
 
+  // Number of stack slots reserved for compiling try-catch. For functions
+  // without try-catch, this is 0. Otherwise, it is the number of local
+  // variables.
+  intptr_t fixed_slot_count() const { return fixed_slot_count_; }
+  void set_fixed_slot_count(intptr_t count) {
+    ASSERT(count >= 0);
+    fixed_slot_count_ = count;
+  }
   TargetEntryInstr* normal_entry() const { return normal_entry_; }
 
   const ParsedFunction& parsed_function() const {
     return parsed_function_;
   }
 
+  const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const {
+    return catch_entries_;
+  }
+
   virtual void PrintTo(BufferFormatter* f) const;
 
  private:
@@ -1278,6 +1334,7 @@
   GrowableArray<CatchBlockEntryInstr*> catch_entries_;
   GrowableArray<Definition*> initial_definitions_;
   intptr_t spill_slot_count_;
+  intptr_t fixed_slot_count_;  // For try-catch in optimized code.
 
   DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr);
 };
@@ -1417,6 +1474,9 @@
   intptr_t catch_try_index() const {
     return catch_try_index_;
   }
+  GrowableArray<Definition*>* initial_definitions() {
+    return &initial_definitions_;
+  }
 
   virtual void PrepareEntry(FlowGraphCompiler* compiler);
 
@@ -1434,6 +1494,7 @@
   BlockEntryInstr* predecessor_;
   const Array& catch_handler_types_;
   const intptr_t catch_try_index_;
+  GrowableArray<Definition*> initial_definitions_;
 
   DISALLOW_COPY_AND_ASSIGN(CatchBlockEntryInstr);
 };
@@ -1662,6 +1723,8 @@
     reaching_defs_ = reaching_defs;
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   // Direct access to inputs_ in order to resize it due to unreachable
   // predecessors.
@@ -1682,7 +1745,7 @@
 
 class ParameterInstr : public Definition {
  public:
-  ParameterInstr(intptr_t index, GraphEntryInstr* block)
+  ParameterInstr(intptr_t index, BlockEntryInstr* block)
       : index_(index), block_(block) { }
 
   DECLARE_INSTRUCTION(Parameter)
@@ -1714,11 +1777,13 @@
 
   virtual CompileType ComputeType() const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
 
   const intptr_t index_;
-  GraphEntryInstr* block_;
+  BlockEntryInstr* block_;
 
   DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
 };
@@ -1763,6 +1828,8 @@
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     ASSERT(i == 0);
@@ -1805,6 +1872,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t token_pos_;
 
@@ -1826,6 +1895,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const intptr_t token_pos_;
 
@@ -1847,6 +1918,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const intptr_t token_pos_;
 
@@ -1896,6 +1969,8 @@
 
   virtual void PrintTo(BufferFormatter* f) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   JoinEntryInstr* successor_;
 
@@ -1990,6 +2065,8 @@
 
   virtual void InheritDeoptTarget(Instruction* other);
 
+  virtual bool MayThrow() const;
+
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value);
 
@@ -2020,6 +2097,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(StoreContextInstr);
 };
@@ -2073,6 +2152,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(RedefinitionInstr);
 };
@@ -2264,6 +2345,8 @@
     return false;
   }
 
+  virtual bool MayThrow() const { return false; }
+
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
   Value* value() const { return inputs_[0]; }
@@ -2322,6 +2405,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Object& value_;
 
@@ -2373,6 +2458,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const intptr_t token_pos_;
   AbstractType& dst_type_;
@@ -2406,6 +2493,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const intptr_t token_pos_;
 
@@ -2440,6 +2529,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const ArgumentDefinitionTestNode& ast_node_;
 
@@ -2462,6 +2553,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(CurrentContextInstr);
 };
@@ -2490,6 +2583,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::All(); }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const ClosureCallNode& ast_node_;
   ZoneGrowableArray<PushArgumentInstr*>* arguments_;
@@ -2552,6 +2647,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::All(); }
 
+  virtual bool MayThrow() const { return true; }
+
  protected:
   friend class FlowGraphOptimizer;
   void set_ic_data(ICData* value) { ic_data_ = value; }
@@ -2601,6 +2698,8 @@
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   InstanceCallInstr* instance_call_;
   const ICData& ic_data_;
@@ -2692,6 +2791,11 @@
 }
 
 
+inline bool BranchInstr::MayThrow() const {
+  return comparison()->MayThrow();
+}
+
+
 class StrictCompareInstr : public ComparisonInstr {
  public:
   StrictCompareInstr(Token::Kind kind, Value* left, Value* right);
@@ -2722,6 +2826,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   // True if the comparison must check for double, Mint or Bigint and
   // use value comparison instead.
@@ -2767,6 +2873,10 @@
         || (receiver_class_id() == kSmiCid);
   }
 
+  bool is_checked_strict_equal() const {
+    return HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
+  }
+
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
   virtual bool CanDeoptimize() const {
@@ -2793,6 +2903,10 @@
     return IsInlinedNumericComparison() ? EffectSet::None() : EffectSet::All();
   }
 
+  virtual bool MayThrow() const {
+    return !IsInlinedNumericComparison() && !is_checked_strict_equal();
+  }
+
  private:
   const ICData* ic_data_;
   const intptr_t token_pos_;
@@ -2867,6 +2981,8 @@
     return IsInlinedNumericComparison() ? EffectSet::None() : EffectSet::All();
   }
 
+  virtual bool MayThrow() const { return !IsInlinedNumericComparison(); }
+
  private:
   const ICData* ic_data_;
   const intptr_t token_pos_;
@@ -2927,6 +3043,8 @@
            (if_false_ == other_if_then_else->if_false_);
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind kind_;
   const intptr_t if_true_;
@@ -2978,6 +3096,8 @@
     is_known_list_constructor_ = value;
   }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const intptr_t token_pos_;
   const Function& function_;
@@ -3014,6 +3134,11 @@
   void mark_last() { is_last_ = true; }
   bool is_last() const { return is_last_; }
 
+  virtual bool MayThrow() const {
+    UNREACHABLE();
+    return false;
+  }
+
  private:
   const LocalVariable& local_;
   bool is_last_;
@@ -3050,6 +3175,11 @@
     return EffectSet::None();
   }
 
+  virtual bool MayThrow() const {
+    UNREACHABLE();
+    return false;
+  }
+
  private:
   const LocalVariable& local_;
   bool is_dead_;
@@ -3084,6 +3214,11 @@
 
   virtual EffectSet Effects() const { return EffectSet::All(); }
 
+  virtual bool MayThrow() const {
+    UNREACHABLE();
+    return true;
+  }
+
  private:
   const NativeBodyNode& ast_node_;
 
@@ -3130,6 +3265,8 @@
   // are marked as having no side-effects.
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   bool CanValueBeSmi() const {
     const intptr_t cid = value()->Type()->ToNullableCid();
@@ -3174,6 +3311,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Field& field_;
 
@@ -3199,6 +3338,7 @@
   virtual EffectSet Dependencies() const;
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
  private:
   const Field& field_;
 
@@ -3229,6 +3369,8 @@
   // are marked as having no side-effects.
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   bool CanValueBeSmi() const {
     const intptr_t cid = value()->Type()->ToNullableCid();
@@ -3288,6 +3430,8 @@
   virtual EffectSet Dependencies() const;
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t index_scale_;
   const intptr_t class_id_;
@@ -3320,6 +3464,8 @@
     return other->AsStringFromCharCode()->cid_ == cid_;
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t cid_;
 
@@ -3374,6 +3520,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const StoreBarrierType emit_store_barrier_;
   const intptr_t index_scale_;
@@ -3399,6 +3547,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BooleanNegateInstr);
 };
@@ -3440,6 +3590,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const intptr_t token_pos_;
   Value* value_;
@@ -3481,6 +3633,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
   // If the result of the allocation is not stored into any field, passed
   // as an argument or used in a phi then it can't alias with any other
   // SSA value.
@@ -3549,6 +3703,8 @@
   Location* locations() { return locations_; }
   void set_locations(Location* locations) { locations_ = locations; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     (*values_)[i] = value;
@@ -3584,6 +3740,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const ConstructorCallNode& ast_node_;
 
@@ -3621,6 +3779,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t token_pos_;
   const intptr_t num_elements_;
@@ -3656,6 +3816,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Function& function_;
   ZoneGrowableArray<PushArgumentInstr*>* arguments_;
@@ -3690,6 +3852,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   intptr_t offset_;
 
@@ -3720,6 +3884,8 @@
   }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadClassIdInstr);
 };
@@ -3784,6 +3950,8 @@
   virtual EffectSet Dependencies() const;
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t offset_in_bytes_;
   const AbstractType& type_;
@@ -3825,6 +3993,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t offset_in_bytes_;
   const AbstractType& type_;
@@ -3861,6 +4031,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   const intptr_t token_pos_;
   const AbstractTypeArguments& type_arguments_;
@@ -3898,6 +4070,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t token_pos_;
   const AbstractTypeArguments& type_arguments_;
@@ -3930,6 +4104,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const ConstructorCallNode& ast_node_;
   const Class& instantiator_class_;
@@ -3957,6 +4133,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t token_pos_;
   const intptr_t num_context_variables_;
@@ -3981,6 +4159,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ChainContextInstr);
 };
@@ -4003,6 +4183,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t token_pos_;
 
@@ -4029,6 +4211,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::All(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const LocalVariable& exception_var_;
   const LocalVariable& stacktrace_var_;
@@ -4063,6 +4247,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(CheckEitherNonSmiInstr);
 };
@@ -4091,6 +4277,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
   Definition* Canonicalize(FlowGraph* flow_graph);
 
  private:
@@ -4121,6 +4309,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxFloat32x4Instr);
 };
@@ -4149,6 +4339,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxUint32x4Instr);
 };
@@ -4177,6 +4369,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxIntegerInstr);
 };
@@ -4208,6 +4402,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
   Definition* Canonicalize(FlowGraph* flow_graph);
 
  private:
@@ -4240,6 +4436,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(UnboxFloat32x4Instr);
 };
@@ -4270,6 +4468,8 @@
   DECLARE_INSTRUCTION(UnboxUint32x4)
   virtual CompileType ComputeType() const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(UnboxUint32x4Instr);
 };
@@ -4302,6 +4502,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(UnboxIntegerInstr);
 };
@@ -4341,6 +4543,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(MathSqrtInstr);
 };
@@ -4394,6 +4598,8 @@
     return op_kind() == other->AsBinaryDoubleOp()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind op_kind_;
 
@@ -4406,11 +4612,11 @@
   BinaryFloat32x4OpInstr(Token::Kind op_kind,
                          Value* left,
                          Value* right,
-                         InstanceCallInstr* instance_call)
+                         intptr_t deopt_id)
       : op_kind_(op_kind) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4447,6 +4653,8 @@
     return op_kind() == other->AsBinaryFloat32x4Op()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind op_kind_;
 
@@ -4457,10 +4665,10 @@
 class Float32x4ShuffleInstr : public TemplateDefinition<1> {
  public:
   Float32x4ShuffleInstr(MethodRecognizer::Kind op_kind, Value* value,
-                        InstanceCallInstr* instance_call)
+                        intptr_t deopt_id)
       : op_kind_(op_kind) {
     SetInputAt(0, value);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* value() const { return inputs_[0]; }
@@ -4502,6 +4710,8 @@
     return op_kind() == other->AsFloat32x4Shuffle()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind op_kind_;
 
@@ -4512,12 +4722,12 @@
 class Float32x4ConstructorInstr : public TemplateDefinition<4> {
  public:
   Float32x4ConstructorInstr(Value* value0, Value* value1, Value* value2,
-                            Value* value3, StaticCallInstr* static_call) {
+                            Value* value3, intptr_t deopt_id) {
     SetInputAt(0, value0);
     SetInputAt(1, value1);
     SetInputAt(2, value2);
     SetInputAt(3, value3);
-    deopt_id_ = static_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* value0() const { return inputs_[0]; }
@@ -4552,6 +4762,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(Float32x4ConstructorInstr);
 };
@@ -4559,9 +4771,9 @@
 
 class Float32x4SplatInstr : public TemplateDefinition<1> {
  public:
-  Float32x4SplatInstr(Value* value, StaticCallInstr* static_call) {
+  Float32x4SplatInstr(Value* value, intptr_t deopt_id) {
     SetInputAt(0, value);
-    deopt_id_ = static_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* value() const { return inputs_[0]; }
@@ -4593,6 +4805,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(Float32x4SplatInstr);
 };
@@ -4600,8 +4814,8 @@
 
 class Float32x4ZeroInstr : public TemplateDefinition<0> {
  public:
-  explicit Float32x4ZeroInstr(StaticCallInstr* static_call) {
-    deopt_id_ = static_call->deopt_id();
+  explicit Float32x4ZeroInstr(intptr_t deopt_id) {
+    deopt_id_ = deopt_id;
   }
 
   Value* value() const { return inputs_[0]; }
@@ -4633,6 +4847,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(Float32x4ZeroInstr);
 };
@@ -4641,11 +4857,11 @@
 class Float32x4ComparisonInstr : public TemplateDefinition<2> {
  public:
   Float32x4ComparisonInstr(MethodRecognizer::Kind op_kind, Value* left,
-                           Value* right, InstanceCallInstr* instance_call)
+                           Value* right, intptr_t deopt_id)
       : op_kind_(op_kind) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4682,6 +4898,8 @@
     return op_kind() == other->AsFloat32x4Comparison()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind op_kind_;
 
@@ -4692,11 +4910,11 @@
 class Float32x4MinMaxInstr : public TemplateDefinition<2> {
  public:
   Float32x4MinMaxInstr(MethodRecognizer::Kind op_kind, Value* left,
-                       Value* right, InstanceCallInstr* instance_call)
+                       Value* right, intptr_t deopt_id)
       : op_kind_(op_kind) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4733,6 +4951,8 @@
     return op_kind() == other->AsFloat32x4MinMax()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind op_kind_;
 
@@ -4743,11 +4963,11 @@
 class Float32x4ScaleInstr : public TemplateDefinition<2> {
  public:
   Float32x4ScaleInstr(MethodRecognizer::Kind op_kind, Value* left,
-                      Value* right, InstanceCallInstr* instance_call)
+                      Value* right, intptr_t deopt_id)
       : op_kind_(op_kind) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4787,6 +5007,8 @@
     return op_kind() == other->AsFloat32x4Scale()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind op_kind_;
 
@@ -4797,9 +5019,9 @@
 class Float32x4SqrtInstr : public TemplateDefinition<1> {
  public:
   Float32x4SqrtInstr(MethodRecognizer::Kind op_kind, Value* left,
-                     InstanceCallInstr* instance_call) : op_kind_(op_kind) {
+                     intptr_t deopt_id) : op_kind_(op_kind) {
     SetInputAt(0, left);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4835,6 +5057,8 @@
     return op_kind() == other->AsFloat32x4Sqrt()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind op_kind_;
 
@@ -4845,9 +5069,9 @@
 class Float32x4ZeroArgInstr : public TemplateDefinition<1> {
  public:
   Float32x4ZeroArgInstr(MethodRecognizer::Kind op_kind, Value* left,
-                        InstanceCallInstr* instance_call) : op_kind_(op_kind) {
+                        intptr_t deopt_id) : op_kind_(op_kind) {
     SetInputAt(0, left);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4883,6 +5107,8 @@
     return op_kind() == other->AsFloat32x4ZeroArg()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind op_kind_;
 
@@ -4893,11 +5119,11 @@
 class Float32x4ClampInstr : public TemplateDefinition<3> {
  public:
   Float32x4ClampInstr(Value* left, Value* lower, Value* upper,
-                      InstanceCallInstr* instance_call) {
+                      intptr_t deopt_id) {
     SetInputAt(0, left);
     SetInputAt(1, lower);
     SetInputAt(2, upper);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4931,6 +5157,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(Float32x4ClampInstr);
 };
@@ -4939,11 +5167,11 @@
 class Float32x4WithInstr : public TemplateDefinition<2> {
  public:
   Float32x4WithInstr(MethodRecognizer::Kind op_kind, Value* left,
-                     Value* replacement, InstanceCallInstr* instance_call)
+                     Value* replacement, intptr_t deopt_id)
       : op_kind_(op_kind) {
     SetInputAt(0, replacement);
     SetInputAt(1, left);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[1]; }
@@ -4983,6 +5211,8 @@
     return op_kind() == other->AsFloat32x4With()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind op_kind_;
 
@@ -4992,9 +5222,9 @@
 
 class Float32x4ToUint32x4Instr : public TemplateDefinition<1> {
  public:
-  Float32x4ToUint32x4Instr(Value* left, InstanceCallInstr* instance_call) {
+  Float32x4ToUint32x4Instr(Value* left, intptr_t deopt_id) {
     SetInputAt(0, left);
-    deopt_id_ = instance_call->deopt_id();
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -5026,11 +5256,318 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(Float32x4ToUint32x4Instr);
 };
 
 
+class Uint32x4BoolConstructorInstr : public TemplateDefinition<4> {
+ public:
+  Uint32x4BoolConstructorInstr(Value* value0, Value* value1, Value* value2,
+                               Value* value3, intptr_t deopt_id) {
+    SetInputAt(0, value0);
+    SetInputAt(1, value1);
+    SetInputAt(2, value2);
+    SetInputAt(3, value3);
+    deopt_id_ = deopt_id;
+  }
+
+  Value* value0() const { return inputs_[0]; }
+  Value* value1() const { return inputs_[1]; }
+  Value* value2() const { return inputs_[2]; }
+  Value* value3() const { return inputs_[3]; }
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual Representation representation() const {
+    return kUnboxedUint32x4;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx >= 0 && idx < 4);
+    return kTagged;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return deopt_id_;
+  }
+
+  DECLARE_INSTRUCTION(Uint32x4BoolConstructor)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AllowsCSE() const { return true; }
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+  virtual bool AttributesEqual(Instruction* other) const { return true; }
+
+  virtual bool MayThrow() const { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Uint32x4BoolConstructorInstr);
+};
+
+
+class Uint32x4GetFlagInstr : public TemplateDefinition<1> {
+ public:
+  Uint32x4GetFlagInstr(MethodRecognizer::Kind op_kind, Value* value,
+                       intptr_t deopt_id)
+      : op_kind_(op_kind) {
+    SetInputAt(0, value);
+    deopt_id_ = deopt_id;
+  }
+
+  Value* value() const { return inputs_[0]; }
+
+  MethodRecognizer::Kind op_kind() const { return op_kind_; }
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual Representation representation() const {
+      return kTagged;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return kUnboxedUint32x4;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return deopt_id_;
+  }
+
+  DECLARE_INSTRUCTION(Uint32x4GetFlag)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AllowsCSE() const { return true; }
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+  virtual bool AttributesEqual(Instruction* other) const {
+    return op_kind() == other->AsUint32x4GetFlag()->op_kind();
+  }
+
+  virtual bool MayThrow() const { return false; }
+
+ private:
+  const MethodRecognizer::Kind op_kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(Uint32x4GetFlagInstr);
+};
+
+
+class Uint32x4SelectInstr : public TemplateDefinition<3> {
+ public:
+  Uint32x4SelectInstr(Value* mask, Value* trueValue, Value* falseValue,
+                      intptr_t deopt_id) {
+    SetInputAt(0, mask);
+    SetInputAt(1, trueValue);
+    SetInputAt(2, falseValue);
+    deopt_id_ = deopt_id;
+  }
+
+  Value* mask() const { return inputs_[0]; }
+  Value* trueValue() const { return inputs_[1]; }
+  Value* falseValue() const { return inputs_[2]; }
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual Representation representation() const {
+      return kUnboxedFloat32x4;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT((idx == 0) || (idx == 1) || (idx == 2));
+    if (idx == 0) {
+      return kUnboxedUint32x4;
+    }
+    return kUnboxedFloat32x4;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return deopt_id_;
+  }
+
+  DECLARE_INSTRUCTION(Uint32x4Select)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AllowsCSE() const { return true; }
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+  virtual bool AttributesEqual(Instruction* other) const { return true; }
+
+  virtual bool MayThrow() const { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Uint32x4SelectInstr);
+};
+
+
+class Uint32x4SetFlagInstr : public TemplateDefinition<2> {
+ public:
+  Uint32x4SetFlagInstr(MethodRecognizer::Kind op_kind, Value* value,
+                       Value* flagValue, intptr_t deopt_id)
+      : op_kind_(op_kind) {
+    SetInputAt(0, value);
+    SetInputAt(1, flagValue);
+    deopt_id_ = deopt_id;
+  }
+
+  Value* value() const { return inputs_[0]; }
+  Value* flagValue() const { return inputs_[1]; }
+
+  MethodRecognizer::Kind op_kind() const { return op_kind_; }
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual Representation representation() const {
+      return kUnboxedUint32x4;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT((idx == 0) || (idx == 1));
+    if (idx == 1) {
+      return kTagged;
+    }
+    return kUnboxedUint32x4;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return deopt_id_;
+  }
+
+  DECLARE_INSTRUCTION(Uint32x4SetFlag)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AllowsCSE() const { return true; }
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+  virtual bool AttributesEqual(Instruction* other) const {
+    return op_kind() == other->AsUint32x4SetFlag()->op_kind();
+  }
+
+  virtual bool MayThrow() const { return false; }
+
+ private:
+  const MethodRecognizer::Kind op_kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(Uint32x4SetFlagInstr);
+};
+
+
+class Uint32x4ToFloat32x4Instr : public TemplateDefinition<1> {
+ public:
+  Uint32x4ToFloat32x4Instr(Value* left, intptr_t deopt_id) {
+    SetInputAt(0, left);
+    deopt_id_ = deopt_id;
+  }
+
+  Value* left() const { return inputs_[0]; }
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual Representation representation() const {
+    return kUnboxedFloat32x4;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return kUnboxedUint32x4;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return deopt_id_;
+  }
+
+  DECLARE_INSTRUCTION(Uint32x4ToFloat32x4)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AllowsCSE() const { return true; }
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+  virtual bool AttributesEqual(Instruction* other) const { return true; }
+
+  virtual bool MayThrow() const { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Uint32x4ToFloat32x4Instr);
+};
+
+
+class BinaryUint32x4OpInstr : public TemplateDefinition<2> {
+ public:
+  BinaryUint32x4OpInstr(Token::Kind op_kind,
+                        Value* left,
+                        Value* right,
+                        intptr_t deopt_id)
+      : op_kind_(op_kind) {
+    SetInputAt(0, left);
+    SetInputAt(1, right);
+    deopt_id_ = deopt_id;
+  }
+
+  Value* left() const { return inputs_[0]; }
+  Value* right() const { return inputs_[1]; }
+
+  Token::Kind op_kind() const { return op_kind_; }
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual Representation representation() const {
+    return kUnboxedUint32x4;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT((idx == 0) || (idx == 1));
+    return kUnboxedUint32x4;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return deopt_id_;
+  }
+
+  DECLARE_INSTRUCTION(BinaryUint32x4Op)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AllowsCSE() const { return true; }
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+  virtual bool AttributesEqual(Instruction* other) const {
+    return op_kind() == other->AsBinaryUint32x4Op()->op_kind();
+  }
+
+  virtual bool MayThrow() const { return false; }
+
+ private:
+  const Token::Kind op_kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(BinaryUint32x4OpInstr);
+};
+
 class BinaryMintOpInstr : public TemplateDefinition<2> {
  public:
   BinaryMintOpInstr(Token::Kind op_kind,
@@ -5085,6 +5622,8 @@
     return op_kind() == other->AsBinaryMintOp()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind op_kind_;
   InstanceCallInstr* instance_call_;
@@ -5141,6 +5680,8 @@
     return op_kind() == other->AsShiftMintOp()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind op_kind_;
 
@@ -5192,6 +5733,8 @@
     return op_kind() == other->AsUnaryMintOp()->op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind op_kind_;
 
@@ -5250,6 +5793,8 @@
   // a power of two.
   bool RightIsPowerOfTwoConstant() const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind op_kind_;
   InstanceCallInstr* instance_call_;
@@ -5289,6 +5834,8 @@
     return other->AsUnarySmiOp()->op_kind() == op_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const Token::Kind op_kind_;
 
@@ -5311,6 +5858,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const intptr_t token_pos_;
 
@@ -5342,6 +5891,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(SmiToDoubleInstr);
 };
@@ -5367,6 +5918,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   InstanceCallInstr* instance_call_;
 
@@ -5399,6 +5952,8 @@
 
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(DoubleToSmiInstr);
 };
@@ -5441,6 +5996,8 @@
     return other->AsDoubleToDouble()->recognized_kind() == recognized_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const MethodRecognizer::Kind recognized_kind_;
 
@@ -5502,6 +6059,8 @@
     return other_invoke->recognized_kind() == recognized_kind();
   }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     (*inputs_)[i] = value;
@@ -5546,6 +6105,8 @@
   virtual EffectSet Dependencies() const;
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   const ICData& unary_checks_;
 
@@ -5578,6 +6139,8 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual bool MayThrow() const { return false; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(CheckSmiInstr);
 };
@@ -5590,13 +6153,13 @@
                        intptr_t array_type,
                        InstanceCallInstr* instance_call)
       : array_type_(array_type) {
-    SetInputAt(0, length);
-    SetInputAt(1, index);
+    SetInputAt(kLengthPos, length);
+    SetInputAt(kIndexPos, index);
     deopt_id_ = instance_call->deopt_id();
   }
 
-  Value* length() const { return inputs_[0]; }
-  Value* index() const { return inputs_[1]; }
+  Value* length() const { return inputs_[kLengthPos]; }
+  Value* index() const { return inputs_[kIndexPos]; }
 
   intptr_t array_type() const { return array_type_; }
 
@@ -5608,6 +6171,8 @@
 
   bool IsRedundant(RangeBoundary length);
 
+  virtual Instruction* Canonicalize(FlowGraph* flow_graph);
+
   // Returns the length offset for array and string types.
   static intptr_t LengthOffsetFor(intptr_t class_id);
 
@@ -5618,7 +6183,14 @@
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
   virtual bool AttributesEqual(Instruction* other) const;
 
+  virtual bool MayThrow() const { return false; }
+
  private:
+  // Give a name to the location/input indices.
+  enum {
+    kLengthPos = 0,
+    kIndexPos = 1
+  };
   intptr_t array_type_;
 
   DISALLOW_COPY_AND_ASSIGN(CheckArrayBoundInstr);
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index e719d84..988dc4f 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -155,7 +155,7 @@
   compiler->GenerateDartCall(deopt_id(),
                              token_pos(),
                              &StubCode::CallClosureFunctionLabel(),
-                             PcDescriptors::kOther,
+                             PcDescriptors::kClosureCall,
                              locs());
   __ Drop(argument_count);
 }
@@ -2230,6 +2230,71 @@
 }
 
 
+LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* Uint32x4SetFlagInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* Uint32x4ToFloat32x4Instr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* BinaryUint32x4OpInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void BinaryUint32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
 LocationSummary* MathSqrtInstr::MakeLocationSummary() const {
   UNIMPLEMENTED();
   return NULL;
@@ -2438,37 +2503,48 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::RegisterOrSmiConstant(length()));
-  locs->set_in(1, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
   return locs;
 }
 
 
 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckArrayBound);
-  if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) {
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+
+  if (length_loc.IsConstant() && index_loc.IsConstant()) {
+    // TODO(srdjan): remove this code once failures are fixed.
+    if ((Smi::Cast(length_loc.constant()).Value() >
+         Smi::Cast(index_loc.constant()).Value()) &&
+        (Smi::Cast(index_loc.constant()).Value() >= 0)) {
+      // This CheckArrayBoundInstr should have been eliminated.
+      return;
+    }
+    ASSERT((Smi::Cast(length_loc.constant()).Value() <=
+            Smi::Cast(index_loc.constant()).Value()) ||
+           (Smi::Cast(index_loc.constant()).Value() < 0));
     // Unconditionally deoptimize for constant bounds checks because they
     // only occur only when index is out-of-bounds.
     __ b(deopt);
     return;
   }
 
-  if (locs()->in(1).IsConstant()) {
-    Register length = locs()->in(0).reg();
-    const Object& constant = locs()->in(1).constant();
-    ASSERT(constant.IsSmi());
-    __ CompareImmediate(length, reinterpret_cast<int32_t>(constant.raw()));
+  if (index_loc.IsConstant()) {
+    Register length = length_loc.reg();
+    const Smi& index = Smi::Cast(index_loc.constant());
+    __ CompareImmediate(length, reinterpret_cast<int32_t>(index.raw()));
     __ b(deopt, LS);
-  } else if (locs()->in(0).IsConstant()) {
-    ASSERT(locs()->in(0).constant().IsSmi());
-    const Smi& smi_const = Smi::Cast(locs()->in(0).constant());
-    Register index = locs()->in(1).reg();
-    __ CompareImmediate(index, reinterpret_cast<int32_t>(smi_const.raw()));
+  } else if (length_loc.IsConstant()) {
+    const Smi& length = Smi::Cast(length_loc.constant());
+    Register index = index_loc.reg();
+    __ CompareImmediate(index, reinterpret_cast<int32_t>(length.raw()));
     __ b(deopt, CS);
   } else {
-    Register length = locs()->in(0).reg();
-    Register index = locs()->in(1).reg();
+    Register length = length_loc.reg();
+    Register index = index_loc.reg();
     __ cmp(index, ShifterOperand(length));
     __ b(deopt, CS);
   }
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index ac0c04f..eba6a8c2 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -3001,17 +3001,17 @@
   ASSERT(v0 == locs()->out().fpu_reg());
   __ subl(ESP, Immediate(16));
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(ESP, -16), v0);
+  __ movss(Address(ESP, 0), v0);
   __ movsd(v0, v1);
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(ESP, -12), v0);
+  __ movss(Address(ESP, 4), v0);
   __ movsd(v0, v2);
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(ESP, -8), v0);
+  __ movss(Address(ESP, 8), v0);
   __ movsd(v0, v3);
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(ESP, -4), v0);
-  __ movups(v0, Address(ESP, -16));
+  __ movss(Address(ESP, 12), v0);
+  __ movups(v0, Address(ESP, 0));
   __ addl(ESP, Immediate(16));
 }
 
@@ -3247,6 +3247,7 @@
   return summary;
 }
 
+
 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   XmmRegister replacement = locs()->in(0).fpu_reg();
   XmmRegister value = locs()->in(1).fpu_reg();
@@ -3258,44 +3259,44 @@
       __ cvtsd2ss(replacement, replacement);
       __ subl(ESP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(ESP, -16), value);
+      __ movups(Address(ESP, 0), value);
       // Write over X value.
-      __ movss(Address(ESP, -16), replacement);
+      __ movss(Address(ESP, 0), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(ESP, -16));
+      __ movups(replacement, Address(ESP, 0));
       __ addl(ESP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithY:
       __ cvtsd2ss(replacement, replacement);
       __ subl(ESP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(ESP, -16), value);
+      __ movups(Address(ESP, 0), value);
       // Write over Y value.
-      __ movss(Address(ESP, -12), replacement);
+      __ movss(Address(ESP, 4), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(ESP, -16));
+      __ movups(replacement, Address(ESP, 0));
       __ addl(ESP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithZ:
       __ cvtsd2ss(replacement, replacement);
       __ subl(ESP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(ESP, -16), value);
+      __ movups(Address(ESP, 0), value);
       // Write over Z value.
-      __ movss(Address(ESP, -8), replacement);
+      __ movss(Address(ESP, 8), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(ESP, -16));
+      __ movups(replacement, Address(ESP, 0));
       __ addl(ESP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithW:
       __ cvtsd2ss(replacement, replacement);
       __ subl(ESP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(ESP, -16), value);
+      __ movups(Address(ESP, 0), value);
       // Write over W value.
-      __ movss(Address(ESP, -4), replacement);
+      __ movss(Address(ESP, 12), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(ESP, -16));
+      __ movups(replacement, Address(ESP, 0));
       __ addl(ESP, Immediate(16));
       break;
     default: UNREACHABLE();
@@ -3319,6 +3320,253 @@
 }
 
 
+LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 4;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  summary->set_in(2, Location::RequiresRegister());
+  summary->set_in(3, Location::RequiresRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
+}
+
+
+void Uint32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register v0 = locs()->in(0).reg();
+  Register v1 = locs()->in(1).reg();
+  Register v2 = locs()->in(2).reg();
+  Register v3 = locs()->in(3).reg();
+  XmmRegister result = locs()->out().fpu_reg();
+  Label x_false, x_done;
+  Label y_false, y_done;
+  Label z_false, z_done;
+  Label w_false, w_done;
+  __ subl(ESP, Immediate(16));
+  __ CompareObject(v0, Bool::True());
+  __ j(NOT_EQUAL, &x_false);
+  __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF));
+  __ jmp(&x_done);
+  __ Bind(&x_false);
+  __ movl(Address(ESP, 0), Immediate(0x0));
+  __ Bind(&x_done);
+
+  __ CompareObject(v1, Bool::True());
+  __ j(NOT_EQUAL, &y_false);
+  __ movl(Address(ESP, 4), Immediate(0xFFFFFFFF));
+  __ jmp(&y_done);
+  __ Bind(&y_false);
+  __ movl(Address(ESP, 4), Immediate(0x0));
+  __ Bind(&y_done);
+
+  __ CompareObject(v2, Bool::True());
+  __ j(NOT_EQUAL, &z_false);
+  __ movl(Address(ESP, 8), Immediate(0xFFFFFFFF));
+  __ jmp(&z_done);
+  __ Bind(&z_false);
+  __ movl(Address(ESP, 8), Immediate(0x0));
+  __ Bind(&z_done);
+
+  __ CompareObject(v3, Bool::True());
+  __ j(NOT_EQUAL, &w_false);
+  __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF));
+  __ jmp(&w_done);
+  __ Bind(&w_false);
+  __ movl(Address(ESP, 12), Immediate(0x0));
+  __ Bind(&w_done);
+
+  __ movups(result, Address(ESP, 0));
+  __ addl(ESP, Immediate(16));
+}
+
+
+LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresRegister());
+  return summary;
+}
+
+
+void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister value = locs()->in(0).fpu_reg();
+  Register result = locs()->out().reg();
+  Label done;
+  Label non_zero;
+  __ subl(ESP, Immediate(16));
+  // Move value to stack.
+  __ movups(Address(ESP, 0), value);
+  switch (op_kind()) {
+    case MethodRecognizer::kUint32x4GetFlagX:
+      __ movl(result, Address(ESP, 0));
+      break;
+    case MethodRecognizer::kUint32x4GetFlagY:
+      __ movl(result, Address(ESP, 4));
+      break;
+    case MethodRecognizer::kUint32x4GetFlagZ:
+      __ movl(result, Address(ESP, 8));
+      break;
+    case MethodRecognizer::kUint32x4GetFlagW:
+      __ movl(result, Address(ESP, 12));
+      break;
+    default: UNREACHABLE();
+  }
+  __ addl(ESP, Immediate(16));
+  __ testl(result, result);
+  __ j(NOT_ZERO, &non_zero, Assembler::kNearJump);
+  __ LoadObject(result, Bool::False());
+  __ jmp(&done);
+  __ Bind(&non_zero);
+  __ LoadObject(result, Bool::True());
+  __ Bind(&done);
+}
+
+
+LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 3;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_in(2, Location::RequiresFpuRegister());
+  summary->set_temp(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Uint32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister mask = locs()->in(0).fpu_reg();
+  XmmRegister trueValue = locs()->in(1).fpu_reg();
+  XmmRegister falseValue = locs()->in(2).fpu_reg();
+  XmmRegister out = locs()->out().fpu_reg();
+  XmmRegister temp = locs()->temp(0).fpu_reg();
+  ASSERT(out == mask);
+  // Copy mask.
+  __ movaps(temp, mask);
+  // Invert it.
+  __ notps(temp);
+  // mask = mask & trueValue.
+  __ andps(mask, trueValue);
+  // temp = temp & falseValue.
+  __ andps(temp, falseValue);
+  // out = mask | temp.
+  __ orps(mask, temp);
+}
+
+
+LocationSummary* Uint32x4SetFlagInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Uint32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister mask = locs()->in(0).fpu_reg();
+  Register flag = locs()->in(1).reg();
+  ASSERT(mask == locs()->out().fpu_reg());
+  __ subl(ESP, Immediate(16));
+  // Copy mask to stack.
+  __ movups(Address(ESP, 0), mask);
+  Label falsePath, exitPath;
+  __ CompareObject(flag, Bool::True());
+  __ j(NOT_EQUAL, &falsePath);
+  switch (op_kind()) {
+    case MethodRecognizer::kUint32x4WithFlagX:
+      __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF));
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movl(Address(ESP, 0), Immediate(0x0));
+    break;
+    case MethodRecognizer::kUint32x4WithFlagY:
+      __ movl(Address(ESP, 4), Immediate(0xFFFFFFFF));
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movl(Address(ESP, 4), Immediate(0x0));
+    break;
+    case MethodRecognizer::kUint32x4WithFlagZ:
+      __ movl(Address(ESP, 8), Immediate(0xFFFFFFFF));
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movl(Address(ESP, 8), Immediate(0x0));
+    break;
+    case MethodRecognizer::kUint32x4WithFlagW:
+      __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF));
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movl(Address(ESP, 12), Immediate(0x0));
+    break;
+    default: UNREACHABLE();
+  }
+  __ Bind(&exitPath);
+  // Copy mask back to register.
+  __ movups(mask, Address(ESP, 0));
+  __ addl(ESP, Immediate(16));
+}
+
+
+LocationSummary* Uint32x4ToFloat32x4Instr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Uint32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // NOP.
+}
+
+
+LocationSummary* BinaryUint32x4OpInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void BinaryUint32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister left = locs()->in(0).fpu_reg();
+  XmmRegister right = locs()->in(1).fpu_reg();
+  ASSERT(left == locs()->out().fpu_reg());
+  switch (op_kind()) {
+    case Token::kBIT_AND: {
+      __ andps(left, right);
+      break;
+    }
+    case Token::kBIT_OR: {
+      __ orps(left, right);
+      break;
+    }
+    case Token::kBIT_XOR: {
+      __ xorps(left, right);
+      break;
+    }
+    default: UNREACHABLE();
+  }
+}
+
+
 LocationSummary* MathSqrtInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
@@ -3645,39 +3893,48 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::RegisterOrSmiConstant(length()));
-  locs->set_in(1, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
   return locs;
 }
 
 
 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckArrayBound);
-  if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) {
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+
+  if (length_loc.IsConstant() && index_loc.IsConstant()) {
+    // TODO(srdjan): remove this code once failures are fixed.
+    if ((Smi::Cast(length_loc.constant()).Value() >
+         Smi::Cast(index_loc.constant()).Value()) &&
+        (Smi::Cast(index_loc.constant()).Value() >= 0)) {
+      // This CheckArrayBoundInstr should have been eliminated.
+      return;
+    }
+    ASSERT((Smi::Cast(length_loc.constant()).Value() <=
+            Smi::Cast(index_loc.constant()).Value()) ||
+           (Smi::Cast(index_loc.constant()).Value() < 0));
     // Unconditionally deoptimize for constant bounds checks because they
     // only occur only when index is out-of-bounds.
     __ jmp(deopt);
     return;
   }
 
-  if (locs()->in(1).IsConstant()) {
-    Register length = locs()->in(0).reg();
-    const Object& constant = locs()->in(1).constant();
-    ASSERT(constant.IsSmi());
-    const int32_t imm =
-        reinterpret_cast<int32_t>(constant.raw());
-    __ cmpl(length, Immediate(imm));
+  if (index_loc.IsConstant()) {
+    Register length = length_loc.reg();
+    const Object& index = Smi::Cast(index_loc.constant());
+    __ cmpl(length, Immediate(reinterpret_cast<int32_t>(index.raw())));
     __ j(BELOW_EQUAL, deopt);
-  } else if (locs()->in(0).IsConstant()) {
-    ASSERT(locs()->in(0).constant().IsSmi());
-    const Smi& smi_const = Smi::Cast(locs()->in(0).constant());
-    Register index = locs()->in(1).reg();
-    __ cmpl(index, Immediate(reinterpret_cast<int32_t>(smi_const.raw())));
+  } else if (length_loc.IsConstant()) {
+    const Smi& length = Smi::Cast(length_loc.constant());
+    Register index = index_loc.reg();
+    __ cmpl(index, Immediate(reinterpret_cast<int32_t>(length.raw())));
     __ j(ABOVE_EQUAL, deopt);
   } else {
-    Register length = locs()->in(0).reg();
-    Register index = locs()->in(1).reg();
+    Register length = length_loc.reg();
+    Register index = index_loc.reg();
     __ cmpl(index, length);
     __ j(ABOVE_EQUAL, deopt);
   }
@@ -4322,7 +4579,7 @@
   compiler->GenerateDartCall(deopt_id(),
                              token_pos(),
                              &StubCode::CallClosureFunctionLabel(),
-                             PcDescriptors::kOther,
+                             PcDescriptors::kClosureCall,
                              locs());
   __ Drop(argument_count);
 }
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 9b3d018..71180ed 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -157,7 +157,7 @@
   compiler->GenerateDartCall(deopt_id(),
                              token_pos(),
                              &StubCode::CallClosureFunctionLabel(),
-                             PcDescriptors::kOther,
+                             PcDescriptors::kClosureCall,
                              locs());
   __ Drop(argument_count);
 }
@@ -2203,6 +2203,72 @@
 }
 
 
+LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* Uint32x4SetFlagInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* Uint32x4ToFloat32x4Instr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Uint32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+LocationSummary* BinaryUint32x4OpInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void BinaryUint32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
 LocationSummary* MathSqrtInstr::MakeLocationSummary() const {
   UNIMPLEMENTED();
   return NULL;
@@ -2414,37 +2480,48 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::RegisterOrSmiConstant(length()));
-  locs->set_in(1, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
   return locs;
 }
 
 
 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckArrayBound);
-  if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) {
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+
+  if (length_loc.IsConstant() && index_loc.IsConstant()) {
+    // TODO(srdjan): remove this code once failures are fixed.
+    if ((Smi::Cast(length_loc.constant()).Value() >
+         Smi::Cast(index_loc.constant()).Value()) &&
+        (Smi::Cast(index_loc.constant()).Value() >= 0)) {
+      // This CheckArrayBoundInstr should have been eliminated.
+      return;
+    }
+    ASSERT((Smi::Cast(length_loc.constant()).Value() <=
+            Smi::Cast(index_loc.constant()).Value()) ||
+           (Smi::Cast(index_loc.constant()).Value() < 0));
     // Unconditionally deoptimize for constant bounds checks because they
     // only occur only when index is out-of-bounds.
     __ b(deopt);
     return;
   }
 
-  if (locs()->in(1).IsConstant()) {
-    Register length = locs()->in(0).reg();
-    const Object& constant = locs()->in(1).constant();
-    ASSERT(constant.IsSmi());
+  if (index_loc.IsConstant()) {
+    Register length = length_loc.reg();
+    const Smi& index = Smi::Cast(index_loc.constant());
     __ BranchUnsignedLessEqual(
-        length, reinterpret_cast<int32_t>(constant.raw()), deopt);
-  } else if (locs()->in(0).IsConstant()) {
-    ASSERT(locs()->in(0).constant().IsSmi());
-    const Smi& smi_const = Smi::Cast(locs()->in(0).constant());
-    Register index = locs()->in(1).reg();
+        length, reinterpret_cast<int32_t>(index.raw()), deopt);
+  } else if (length_loc.IsConstant()) {
+    const Smi& length = Smi::Cast(length_loc.constant());
+    Register index = index_loc.reg();
     __ BranchUnsignedGreaterEqual(
-        index, reinterpret_cast<int32_t>(smi_const.raw()), deopt);
+        index, reinterpret_cast<int32_t>(length.raw()), deopt);
   } else {
-    Register length = locs()->in(0).reg();
-    Register index = locs()->in(1).reg();
+    Register length = length_loc.reg();
+    Register index = index_loc.reg();
     __ BranchUnsignedGreaterEqual(index, length, deopt);
   }
 }
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index c79b1e4..68f2bd0 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -3005,17 +3005,17 @@
   ASSERT(v0 == locs()->out().fpu_reg());
   __ subq(RSP, Immediate(16));
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(RSP, -16), v0);
+  __ movss(Address(RSP, 0), v0);
   __ movsd(v0, v1);
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(RSP, -12), v0);
+  __ movss(Address(RSP, 4), v0);
   __ movsd(v0, v2);
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(RSP, -8), v0);
+  __ movss(Address(RSP, 8), v0);
   __ movsd(v0, v3);
   __ cvtsd2ss(v0, v0);
-  __ movss(Address(RSP, -4), v0);
-  __ movups(v0, Address(RSP, -16));
+  __ movss(Address(RSP, 12), v0);
+  __ movups(v0, Address(RSP, 0));
   __ addq(RSP, Immediate(16));
 }
 
@@ -3251,6 +3251,7 @@
   return summary;
 }
 
+
 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   XmmRegister replacement = locs()->in(0).fpu_reg();
   XmmRegister value = locs()->in(1).fpu_reg();
@@ -3262,44 +3263,44 @@
       __ cvtsd2ss(replacement, replacement);
       __ subq(RSP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(RSP, -16), value);
+      __ movups(Address(RSP, 0), value);
       // Write over X value.
-      __ movss(Address(RSP, -16), replacement);
+      __ movss(Address(RSP, 0), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(RSP, -16));
+      __ movups(replacement, Address(RSP, 0));
       __ addq(RSP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithY:
       __ cvtsd2ss(replacement, replacement);
       __ subq(RSP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(RSP, -16), value);
+      __ movups(Address(RSP, 0), value);
       // Write over Y value.
-      __ movss(Address(RSP, -12), replacement);
+      __ movss(Address(RSP, 4), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(RSP, -16));
+      __ movups(replacement, Address(RSP, 0));
       __ addq(RSP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithZ:
       __ cvtsd2ss(replacement, replacement);
       __ subq(RSP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(RSP, -16), value);
+      __ movups(Address(RSP, 0), value);
       // Write over Z value.
-      __ movss(Address(RSP, -8), replacement);
+      __ movss(Address(RSP, 8), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(RSP, -16));
+      __ movups(replacement, Address(RSP, 0));
       __ addq(RSP, Immediate(16));
       break;
     case MethodRecognizer::kFloat32x4WithW:
       __ cvtsd2ss(replacement, replacement);
       __ subq(RSP, Immediate(16));
       // Move value to stack.
-      __ movups(Address(RSP, -16), value);
+      __ movups(Address(RSP, 0), value);
       // Write over W value.
-      __ movss(Address(RSP, -4), replacement);
+      __ movss(Address(RSP, 12), replacement);
       // Move updated value into output register.
-      __ movups(replacement, Address(RSP, -16));
+      __ movups(replacement, Address(RSP, 0));
       __ addq(RSP, Immediate(16));
       break;
     default: UNREACHABLE();
@@ -3323,6 +3324,270 @@
 }
 
 
+LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 4;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  summary->set_in(2, Location::RequiresRegister());
+  summary->set_in(3, Location::RequiresRegister());
+  summary->set_temp(0, Location::RequiresRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
+}
+
+
+void Uint32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register v0 = locs()->in(0).reg();
+  Register v1 = locs()->in(1).reg();
+  Register v2 = locs()->in(2).reg();
+  Register v3 = locs()->in(3).reg();
+  Register temp = locs()->temp(0).reg();
+  XmmRegister result = locs()->out().fpu_reg();
+  Label x_false, x_done;
+  Label y_false, y_done;
+  Label z_false, z_done;
+  Label w_false, w_done;
+  __ subq(RSP, Immediate(16));
+
+  __ CompareObject(v0, Bool::True());
+  __ j(NOT_EQUAL, &x_false);
+  __ movq(temp, Immediate(0xFFFFFFFF));
+  __ jmp(&x_done);
+  __ Bind(&x_false);
+  __ movq(temp, Immediate(0x0));
+  __ Bind(&x_done);
+  __ movl(Address(RSP, 0), temp);
+
+  __ CompareObject(v1, Bool::True());
+  __ j(NOT_EQUAL, &y_false);
+  __ movq(temp, Immediate(0xFFFFFFFF));
+  __ jmp(&y_done);
+  __ Bind(&y_false);
+  __ movq(temp, Immediate(0x0));
+  __ Bind(&y_done);
+  __ movl(Address(RSP, 4), temp);
+
+  __ CompareObject(v2, Bool::True());
+  __ j(NOT_EQUAL, &z_false);
+  __ movq(temp, Immediate(0xFFFFFFFF));
+  __ jmp(&z_done);
+  __ Bind(&z_false);
+  __ movq(temp, Immediate(0x0));
+  __ Bind(&z_done);
+  __ movl(Address(RSP, 8), temp);
+
+  __ CompareObject(v3, Bool::True());
+  __ j(NOT_EQUAL, &w_false);
+  __ movq(temp, Immediate(0xFFFFFFFF));
+  __ jmp(&w_done);
+  __ Bind(&w_false);
+  __ movq(temp, Immediate(0x0));
+  __ Bind(&w_done);
+  __ movl(Address(RSP, 12), temp);
+
+  __ movups(result, Address(RSP, 0));
+  __ addq(RSP, Immediate(16));
+}
+
+
+LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresRegister());
+  return summary;
+}
+
+
+void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister value = locs()->in(0).fpu_reg();
+  Register result = locs()->out().reg();
+  Label done;
+  Label non_zero;
+  __ subq(RSP, Immediate(16));
+  // Move value to stack.
+  __ movups(Address(RSP, 0), value);
+  switch (op_kind()) {
+    case MethodRecognizer::kUint32x4GetFlagX:
+      __ movl(result, Address(RSP, 0));
+      break;
+    case MethodRecognizer::kUint32x4GetFlagY:
+      __ movl(result, Address(RSP, 4));
+      break;
+    case MethodRecognizer::kUint32x4GetFlagZ:
+      __ movl(result, Address(RSP, 8));
+      break;
+    case MethodRecognizer::kUint32x4GetFlagW:
+      __ movl(result, Address(RSP, 12));
+      break;
+    default: UNREACHABLE();
+  }
+  __ addq(RSP, Immediate(16));
+  __ testl(result, result);
+  __ j(NOT_ZERO, &non_zero, Assembler::kNearJump);
+  __ LoadObject(result, Bool::False());
+  __ jmp(&done);
+  __ Bind(&non_zero);
+  __ LoadObject(result, Bool::True());
+  __ Bind(&done);
+}
+
+
+LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 3;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_in(2, Location::RequiresFpuRegister());
+  summary->set_temp(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Uint32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister mask = locs()->in(0).fpu_reg();
+  XmmRegister trueValue = locs()->in(1).fpu_reg();
+  XmmRegister falseValue = locs()->in(2).fpu_reg();
+  XmmRegister out = locs()->out().fpu_reg();
+  XmmRegister temp = locs()->temp(0).fpu_reg();
+  ASSERT(out == mask);
+  // Copy mask.
+  __ movaps(temp, mask);
+  // Invert it.
+  __ notps(temp);
+  // mask = mask & trueValue.
+  __ andps(mask, trueValue);
+  // temp = temp & falseValue.
+  __ andps(temp, falseValue);
+  // out = mask | temp.
+  __ orps(mask, temp);
+}
+
+
+LocationSummary* Uint32x4SetFlagInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  summary->set_temp(0, Location::RequiresRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Uint32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister mask = locs()->in(0).fpu_reg();
+  Register flag = locs()->in(1).reg();
+  Register temp = locs()->temp(0).reg();
+  ASSERT(mask == locs()->out().fpu_reg());
+  __ subq(RSP, Immediate(16));
+  // Copy mask to stack.
+  __ movups(Address(RSP, 0), mask);
+  Label falsePath, exitPath;
+  __ CompareObject(flag, Bool::True());
+  __ j(NOT_EQUAL, &falsePath);
+  switch (op_kind()) {
+    case MethodRecognizer::kUint32x4WithFlagX:
+      __ movq(temp, Immediate(0xFFFFFFFF));
+      __ movl(Address(RSP, 0), temp);
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movq(temp, Immediate(0x0));
+      __ movl(Address(RSP, 0), temp);
+    break;
+    case MethodRecognizer::kUint32x4WithFlagY:
+      __ movq(temp, Immediate(0xFFFFFFFF));
+      __ movl(Address(RSP, 4), temp);
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movq(temp, Immediate(0x0));
+      __ movl(Address(RSP, 4), temp);
+    break;
+    case MethodRecognizer::kUint32x4WithFlagZ:
+      __ movq(temp, Immediate(0xFFFFFFFF));
+      __ movl(Address(RSP, 8), temp);
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movq(temp, Immediate(0x0));
+      __ movl(Address(RSP, 8), temp);
+    break;
+    case MethodRecognizer::kUint32x4WithFlagW:
+      __ movq(temp, Immediate(0xFFFFFFFF));
+      __ movl(Address(RSP, 12), temp);
+      __ jmp(&exitPath);
+      __ Bind(&falsePath);
+      __ movq(temp, Immediate(0x0));
+      __ movl(Address(RSP, 12), temp);
+    break;
+    default: UNREACHABLE();
+  }
+  __ Bind(&exitPath);
+  // Copy mask back to register.
+  __ movups(mask, Address(RSP, 0));
+  __ addq(RSP, Immediate(16));
+}
+
+
+LocationSummary* Uint32x4ToFloat32x4Instr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Uint32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // NOP.
+}
+
+
+LocationSummary* BinaryUint32x4OpInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void BinaryUint32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister left = locs()->in(0).fpu_reg();
+  XmmRegister right = locs()->in(1).fpu_reg();
+  ASSERT(left == locs()->out().fpu_reg());
+  switch (op_kind()) {
+    case Token::kBIT_AND: {
+      __ andps(left, right);
+      break;
+    }
+    case Token::kBIT_OR: {
+      __ orps(left, right);
+      break;
+    }
+    case Token::kBIT_XOR: {
+      __ xorps(left, right);
+      break;
+    }
+    default: UNREACHABLE();
+  }
+}
+
+
 LocationSummary* MathSqrtInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
@@ -3664,39 +3929,48 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::RegisterOrSmiConstant(length()));
-  locs->set_in(1, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
   return locs;
 }
 
 
 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckArrayBound);
-  if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) {
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+
+  if (length_loc.IsConstant() && index_loc.IsConstant()) {
+    // TODO(srdjan): remove this code once failures are fixed.
+    if ((Smi::Cast(length_loc.constant()).Value() >
+         Smi::Cast(index_loc.constant()).Value()) &&
+        (Smi::Cast(index_loc.constant()).Value() >= 0)) {
+      // This CheckArrayBoundInstr should have been eliminated.
+      return;
+    }
+    ASSERT((Smi::Cast(length_loc.constant()).Value() <=
+            Smi::Cast(index_loc.constant()).Value()) ||
+           (Smi::Cast(index_loc.constant()).Value() < 0));
     // Unconditionally deoptimize for constant bounds checks because they
     // only occur only when index is out-of-bounds.
     __ jmp(deopt);
     return;
   }
 
-  if (locs()->in(1).IsConstant()) {
-    Register length = locs()->in(0).reg();
-    const Object& constant = locs()->in(1).constant();
-    ASSERT(constant.IsSmi());
-    const int64_t imm =
-        reinterpret_cast<int64_t>(constant.raw());
-    __ cmpq(length, Immediate(imm));
+  if (index_loc.IsConstant()) {
+    Register length = length_loc.reg();
+    const Smi& index = Smi::Cast(index_loc.constant());
+    __ cmpq(length, Immediate(reinterpret_cast<int64_t>(index.raw())));
     __ j(BELOW_EQUAL, deopt);
-  } else if (locs()->in(0).IsConstant()) {
-    ASSERT(locs()->in(0).constant().IsSmi());
-    const Smi& smi_const = Smi::Cast(locs()->in(0).constant());
-    Register index = locs()->in(1).reg();
-    __ cmpq(index, Immediate(reinterpret_cast<int64_t>(smi_const.raw())));
+  } else if (length_loc.IsConstant()) {
+    const Smi& length = Smi::Cast(length_loc.constant());
+    Register index = index_loc.reg();
+    __ cmpq(index, Immediate(reinterpret_cast<int64_t>(length.raw())));
     __ j(ABOVE_EQUAL, deopt);
   } else {
-    Register length = locs()->in(0).reg();
-    Register index = locs()->in(1).reg();
+    Register length = length_loc.reg();
+    Register index = index_loc.reg();
     __ cmpq(index, length);
     __ j(ABOVE_EQUAL, deopt);
   }
@@ -3948,7 +4222,7 @@
   compiler->GenerateDartCall(deopt_id(),
                              token_pos(),
                              &StubCode::CallClosureFunctionLabel(),
-                             PcDescriptors::kOther,
+                             PcDescriptors::kClosureCall,
                              locs());
   __ Drop(argument_count);
 }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 1a095e6..ee4543b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -71,6 +71,8 @@
 Array* Object::empty_array_ = NULL;
 Instance* Object::sentinel_ = NULL;
 Instance* Object::transition_sentinel_ = NULL;
+Instance* Object::unknown_constant_ = NULL;
+Instance* Object::non_constant_ = NULL;
 Bool* Object::bool_true_ = NULL;
 Bool* Object::bool_false_ = NULL;
 LanguageError* Object::snapshot_writer_error_ = NULL;
@@ -321,6 +323,8 @@
   empty_array_ = Array::ReadOnlyHandle(isolate);
   sentinel_ = Instance::ReadOnlyHandle(isolate);
   transition_sentinel_ = Instance::ReadOnlyHandle(isolate);
+  unknown_constant_ =  Instance::ReadOnlyHandle(isolate);
+  non_constant_ =  Instance::ReadOnlyHandle(isolate);
   bool_true_ = Bool::ReadOnlyHandle(isolate);
   bool_false_ = Bool::ReadOnlyHandle(isolate);
   snapshot_writer_error_ = LanguageError::ReadOnlyHandle(isolate);
@@ -384,6 +388,14 @@
         Object::Allocate(kNullCid, Instance::InstanceSize(), Heap::kOld);
   }
 
+  // Allocate and initialize optimizing compiler constants.
+  {
+    *unknown_constant_ ^=
+        Object::Allocate(kNullCid, Instance::InstanceSize(), Heap::kOld);
+    *non_constant_ ^=
+        Object::Allocate(kNullCid, Instance::InstanceSize(), Heap::kOld);
+  }
+
   cls = Class::New<Instance>(kDynamicCid);
   cls.set_is_finalized();
   cls.set_is_abstract();
@@ -524,6 +536,10 @@
   ASSERT(sentinel_->IsInstance());
   ASSERT(!transition_sentinel_->IsSmi());
   ASSERT(transition_sentinel_->IsInstance());
+  ASSERT(!unknown_constant_->IsSmi());
+  ASSERT(unknown_constant_->IsInstance());
+  ASSERT(!non_constant_->IsSmi());
+  ASSERT(non_constant_->IsInstance());
   ASSERT(!bool_true_->IsSmi());
   ASSERT(bool_true_->IsBool());
   ASSERT(!bool_false_->IsSmi());
@@ -6541,7 +6557,7 @@
 }
 
 
-static bool IsPrivate(const String& name) {
+bool Library::IsPrivate(const String& name) {
   if (ShouldBePrivate(name)) return true;
   // Factory names: List._fromLiteral.
   for (intptr_t i = 1; i < name.Length() - 1; i++) {
@@ -7081,6 +7097,7 @@
     case PcDescriptors::kLazyDeoptJump: return "lazy-deopt   ";
     case PcDescriptors::kIcCall:        return "ic-call      ";
     case PcDescriptors::kFuncCall:      return "fn-call      ";
+    case PcDescriptors::kClosureCall:   return "closure-call ";
     case PcDescriptors::kReturn:        return "return       ";
     case PcDescriptors::kOther:         return "other        ";
   }
@@ -9177,6 +9194,10 @@
     return "sentinel";
   } else if (raw() == Object::transition_sentinel().raw()) {
     return "transition_sentinel";
+  } else if (raw() == Object::unknown_constant().raw()) {
+    return "unknown_constant";
+  } else if (raw() == Object::non_constant().raw()) {
+    return "non_constant";
   } else if (Isolate::Current()->no_gc_scope_depth() > 0) {
     // Can occur when running disassembler.
     return "Instance";
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 6d3a70f..2173395 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -321,6 +321,16 @@
     return *transition_sentinel_;
   }
 
+  // Compiler's constant propagation constants.
+  static const Instance& unknown_constant() {
+    ASSERT(unknown_constant_ != NULL);
+    return *unknown_constant_;
+  }
+  static const Instance& non_constant() {
+    ASSERT(non_constant_ != NULL);
+    return *non_constant_;
+  }
+
   static const Bool& bool_true() {
     ASSERT(bool_true_ != NULL);
     return *bool_true_;
@@ -523,6 +533,8 @@
   static Array* empty_array_;
   static Instance* sentinel_;
   static Instance* transition_sentinel_;
+  static Instance* unknown_constant_;
+  static Instance* non_constant_;
   static Bool* bool_true_;
   static Bool* bool_false_;
   static LanguageError* snapshot_writer_error_;
@@ -2211,6 +2223,8 @@
   // mismatch found.
   static void CheckFunctionFingerprints();
 
+  static bool IsPrivate(const String& name);
+
  private:
   static const int kInitialImportsCapacity = 4;
   static const int kImportsCapacityIncrement = 8;
@@ -2421,7 +2435,8 @@
     kPatchCode,        // Buffer for patching code entry.
     kLazyDeoptJump,    // Lazy deoptimization trampoline.
     kIcCall,           // IC call.
-    kFuncCall,         // Call to known target, e.g. static call, closure call.
+    kFuncCall,         // Call to known target, e.g. static call.
+    kClosureCall,      // Closure call.
     kReturn,           // Return from function.
     kOther
   };
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 6b527f6..10b63c5 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -40,6 +40,15 @@
     return *reinterpret_cast<uword*>(sp_ + (kSavedPcSlotFromSp * kWordSize));
   }
 
+  // The pool pointer is not implemented on all architectures.
+  static int SavedCallerPpSlotFromFp() {
+    if (kSavedCallerPpSlotFromFp != kSavedCallerFpSlotFromFp) {
+      return kSavedCallerPpSlotFromFp;
+    }
+    UNREACHABLE();
+    return 0;
+  }
+
   void set_pc(uword value) {
     *reinterpret_cast<uword*>(sp_ + (kSavedPcSlotFromSp * kWordSize)) = value;
   }
diff --git a/runtime/vm/stack_frame_arm.h b/runtime/vm/stack_frame_arm.h
index ae669bf..5ddbc82 100644
--- a/runtime/vm/stack_frame_arm.h
+++ b/runtime/vm/stack_frame_arm.h
@@ -11,7 +11,9 @@
 
                |                    | <- TOS
 Callee frame   | ...                |
-               | current LR         |    (PC of current frame)
+               | saved PP           |    (PP of current frame)
+               | saved FP           |    (FP of current frame)
+               | saved LR           |    (PC of current frame)
                | callee's PC marker |
                +--------------------+
 Current frame  | ...                | <- SP of current frame
@@ -25,11 +27,14 @@
                |  ...               |
 */
 
+static const int kDartFrameFixedSize = 4;  // PP, FP, LR, PC marker.
 static const int kSavedPcSlotFromSp = -2;
 static const int kFirstLocalSlotFromFp = -2;
+static const int kSavedCallerPpSlotFromFp = -1;
 static const int kSavedCallerFpSlotFromFp = 0;
+static const int kSavedCallerPcSlotFromFp = 1;
 static const int kPcMarkerSlotFromFp = 2;
-static const int kParamEndSlotFromFp = 2;  // Same slot as current pc marker.
+static const int kParamEndSlotFromFp = 2;  // One slot past last parameter.
 static const int kCallerSpSlotFromFp = 3;
 
 // Entry and exit frame layout.
diff --git a/runtime/vm/stack_frame_ia32.h b/runtime/vm/stack_frame_ia32.h
index 10db2aa..4ef81ae 100644
--- a/runtime/vm/stack_frame_ia32.h
+++ b/runtime/vm/stack_frame_ia32.h
@@ -11,7 +11,8 @@
 
                |                    | <- TOS
 Callee frame   | ...                |
-               | current ret addr   |    (PC of current frame)
+               | saved EBP          |    (EBP of current frame)
+               | saved PC           |    (PC of current frame)
                +--------------------+
 Current frame  | ...                | <- ESP of current frame
                | first local        |
@@ -23,13 +24,18 @@
                |  ...               |
 */
 
+static const int kDartFrameFixedSize = 3;  // PC marker, EBP, PC.
 static const int kSavedPcSlotFromSp = -1;
 static const int kFirstLocalSlotFromFp = -2;
 static const int kPcMarkerSlotFromFp = -1;
 static const int kSavedCallerFpSlotFromFp = 0;
-static const int kParamEndSlotFromFp = 1;  // Same slot as caller's ret addr.
+static const int kSavedCallerPcSlotFromFp = 1;
+static const int kParamEndSlotFromFp = 1;  // One slot past last parameter.
 static const int kCallerSpSlotFromFp = 2;
 
+// No pool pointer on IA32 (indicated by aliasing saved fp).
+static const int kSavedCallerPpSlotFromFp = kSavedCallerFpSlotFromFp;
+
 // Entry and exit frame layout.
 static const int kSavedContextSlotFromEntryFp = -5;
 static const int kExitLinkSlotFromEntryFp = -4;
diff --git a/runtime/vm/stack_frame_mips.h b/runtime/vm/stack_frame_mips.h
index 57e387e..c3e9122 100644
--- a/runtime/vm/stack_frame_mips.h
+++ b/runtime/vm/stack_frame_mips.h
@@ -25,11 +25,14 @@
                |  ...               |
 */
 
+static const int kDartFrameFixedSize = 4;  // PP, FP, RA, PC marker.
 static const int kSavedPcSlotFromSp = -2;
 static const int kFirstLocalSlotFromFp = -2;
+static const int kSavedCallerPpSlotFromFp = -1;
 static const int kSavedCallerFpSlotFromFp = 0;
+static const int kSavedCallerPcSlotFromFp = 1;
 static const int kPcMarkerSlotFromFp = 2;
-static const int kParamEndSlotFromFp = 2;  // Same slot as current pc marker.
+static const int kParamEndSlotFromFp = 2;  // One slot past last parameter.
 static const int kCallerSpSlotFromFp = 3;
 
 // Entry and exit frame layout.
diff --git a/runtime/vm/stack_frame_x64.h b/runtime/vm/stack_frame_x64.h
index 552bd98..fb6e11e 100644
--- a/runtime/vm/stack_frame_x64.h
+++ b/runtime/vm/stack_frame_x64.h
@@ -11,7 +11,8 @@
 
                |                    | <- TOS
 Callee frame   | ...                |
-               | current ret addr   |    (PC of current frame)
+               | saved RBP          |    (RBP of current frame)
+               | saved PC           |    (PC of current frame)
                +--------------------+
 Current frame  | ...                | <- RSP of current frame
                | first local        |
@@ -23,13 +24,18 @@
                |  ...               |
 */
 
+static const int kDartFrameFixedSize = 3;  // PC marker, RBP, PC.
 static const int kSavedPcSlotFromSp = -1;
 static const int kFirstLocalSlotFromFp = -2;
 static const int kPcMarkerSlotFromFp = -1;
 static const int kSavedCallerFpSlotFromFp = 0;
-static const int kParamEndSlotFromFp = 1;  // Same slot as caller's ret addr.
+static const int kSavedCallerPcSlotFromFp = 1;
+static const int kParamEndSlotFromFp = 1;  // One slot past last parameter.
 static const int kCallerSpSlotFromFp = 2;
 
+// No pool pointer on X64 (indicated by aliasing saved fp).
+static const int kSavedCallerPpSlotFromFp = kSavedCallerFpSlotFromFp;
+
 // Entry and exit frame layout.
 static const int kSavedContextSlotFromEntryFp = -9;
 static const int kExitLinkSlotFromEntryFp = -8;
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 0f54897..79e9d7b 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -31,6 +31,7 @@
   V(FixCallersTarget)                                                          \
   V(Deoptimize)                                                                \
   V(DeoptimizeLazy)                                                            \
+  V(BreakpointClosure)                                                         \
   V(BreakpointStatic)                                                          \
   V(BreakpointReturn)                                                          \
   V(Subtype1TestCache)                                                         \
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 50fecc1..558ad90 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -331,22 +331,26 @@
 // GC can occur only after frame is fully rewritten.
 // Stack after EnterFrame(...) below:
 //   +------------------+
-//   | Saved FP         | <- TOS
+//   | Saved PP         | <- TOS
+//   +------------------+
+//   | Saved FP         | <- FP of stub
 //   +------------------+
 //   | Saved LR         |  (deoptimization point)
 //   +------------------+
-//   | stub pc marker   |  (necessary to keep constant offset SP - Saved LR.
+//   | PC marker        |
 //   +------------------+
-//   | optimized frame  | <- SP of optimized code
-//   |  ...             |
+//   | ...              | <- SP of optimized frame
 //
 // Parts of the code cannot GC, part of the code can GC.
 static void GenerateDeoptimizationSequence(Assembler* assembler,
                                            bool preserve_result) {
-  __ EnterStubFrame();  // Do not save pp (implicit saved regs to fp offset).
+  // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
+  // is no need to set the correct PC marker or load PP, since they get patched.
+  __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0);
   // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
-  const intptr_t saved_r0_offset_from_fp = -(kNumberOfCpuRegisters - R0);
+  const intptr_t saved_result_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
   // Result in R0 is preserved as part of pushing all registers below.
 
   // TODO(regis): Should we align the stack before pushing the fpu registers?
@@ -361,31 +365,31 @@
   __ mov(R0, ShifterOperand(SP));  // Pass address of saved registers block.
   __ ReserveAlignedFrameSpace(0);
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry);
-  // Result (R0) is stack-size (FP - SP) in bytes, incl. the return address.
+  // Result (R0) is stack-size (FP - SP) in bytes.
 
   if (preserve_result) {
     // Restore result into R1 temporarily.
-    __ ldr(R1, Address(FP, saved_r0_offset_from_fp * kWordSize));
+    __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize));
   }
 
-  __ LeaveStubFrame();  // Restores FP and LR from stack.
+  __ LeaveDartFrame();
   __ sub(SP, FP, ShifterOperand(R0));
 
-  __ EnterStubFrame();
-  __ mov(R0, ShifterOperand(SP));  // Get last FP address.
+  // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
+  // is no need to set the correct PC marker or load PP, since they get patched.
+  __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0);
+  __ mov(R0, ShifterOperand(FP));  // Get last FP address.
   if (preserve_result) {
-    __ Push(R1);  // Preserve result.
+    __ Push(R1);  // Preserve result as first local.
   }
   __ ReserveAlignedFrameSpace(0);
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry);  // Pass last FP in R0.
-  // Result (R0) is our FP.
   if (preserve_result) {
     // Restore result into R1.
-    __ ldr(R1, Address(FP, -1 * kWordSize));
+    __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
   }
   // Code above cannot cause GC.
-  __ LeaveStubFrame();
-  __ mov(FP, ShifterOperand(R0));
+  __ LeaveDartFrame();
 
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
@@ -1548,6 +1552,12 @@
 }
 
 
+void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
+  // TODO(hausner): implement this stub.
+  __ Branch(&StubCode::CallClosureFunctionLabel());
+}
+
+
 //  LR: return address (Dart code).
 //  R4: arguments descriptor array.
 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 7c22076..90f5da4 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -323,22 +323,25 @@
 // - Fill the unoptimized frame.
 // - Materialize objects that require allocation (e.g. Double instances).
 // GC can occur only after frame is fully rewritten.
-// Stack after EnterFrame(0) below:
+// Stack after EnterDartFrame(0) below:
 //   +------------------+
-//   | Saved FP         | <- TOS
+//   | PC marker        | <- TOS
+//   +------------------+
+//   | Saved FP         | <- FP of stub
 //   +------------------+
 //   | return-address   |  (deoptimization point)
 //   +------------------+
-//   | optimized frame  |
-//   |  ...             |
+//   | ...              | <- SP of optimized frame
 //
 // Parts of the code cannot GC, part of the code can GC.
 static void GenerateDeoptimizationSequence(Assembler* assembler,
-                                           bool preserve_eax) {
-  __ EnterFrame(0);
+                                           bool preserve_result) {
+  // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
+  __ EnterDartFrame(0);
   // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
-  const intptr_t saved_eax_offset_from_ebp = -(kNumberOfCpuRegisters - EAX);
+  const intptr_t saved_result_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - EAX);
   // Result in EAX is preserved as part of pushing all registers below.
 
   // Push registers in their enumeration order: lowest register number at
@@ -358,41 +361,39 @@
   __ ReserveAlignedFrameSpace(1 * kWordSize);
   __ movl(Address(ESP, 0), ECX);  // Start of register block.
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry);
-  // Result (EAX) is stack-size (FP - SP) in bytes, incl. the return address.
+  // Result (EAX) is stack-size (FP - SP) in bytes.
 
-  if (preserve_eax) {
+  if (preserve_result) {
     // Restore result into EBX temporarily.
-    __ movl(EBX, Address(EBP, saved_eax_offset_from_ebp * kWordSize));
+    __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize));
   }
 
   __ LeaveFrame();
   __ popl(EDX);  // Preserve return address.
-  __ movl(ESP, EBP);
-  __ subl(ESP, EAX);
-  __ movl(Address(ESP, 0), EDX);
+  __ movl(ESP, EBP);  // Discard optimized frame.
+  __ subl(ESP, EAX);  // Reserve space for deoptimized frame.
+  __ pushl(EDX);  // Restore return address.
 
-  __ EnterFrame(0);
-  __ movl(ECX, ESP);  // Get last FP address.
-  if (preserve_eax) {
-    __ pushl(EBX);  // Preserve result.
+  // Leaf runtime function DeoptimizeFillFrame expects a Dart frame.
+  __ EnterDartFrame(0);
+  if (preserve_result) {
+    __ pushl(EBX);  // Preserve result as first local.
   }
   __ ReserveAlignedFrameSpace(1 * kWordSize);
-  __ movl(Address(ESP, 0), ECX);
+  __ movl(Address(ESP, 0), EBP);  // Pass last FP as parameter on stack.
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry);
-  // Result (EAX) is our FP.
-  if (preserve_eax) {
+  if (preserve_result) {
     // Restore result into EBX.
-    __ movl(EBX, Address(EBP, -1 * kWordSize));
+    __ movl(EBX, Address(EBP, kFirstLocalSlotFromFp * kWordSize));
   }
   // Code above cannot cause GC.
   __ LeaveFrame();
-  __ movl(EBP, EAX);
 
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
   __ EnterStubFrame();
-  if (preserve_eax) {
+  if (preserve_result) {
     __ pushl(EBX);  // Preserve result, it will be GC-d here.
   }
   __ pushl(Immediate(Smi::RawValue(0)));  // Space for the result.
@@ -401,7 +402,7 @@
   // of the bottom-most frame. They were used as materialization arguments.
   __ popl(EBX);
   __ SmiUntag(EBX);
-  if (preserve_eax) {
+  if (preserve_result) {
     __ popl(EAX);  // Restore result.
   }
   __ LeaveFrame();
@@ -1708,6 +1709,17 @@
 
 
 //  EDX: Arguments descriptor array.
+void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ pushl(EDX);  // Push arguments descriptor.
+  __ CallRuntime(kBreakpointClosureHandlerRuntimeEntry);
+  __ popl(EDX);  // Restore arguments descriptor.
+  __ LeaveFrame();
+  __ jmp(&StubCode::CallClosureFunctionLabel());
+}
+
+
+//  EDX: Arguments descriptor array.
 //  TOS(0): return address (Dart code).
 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index b85e0bc..b985b5a 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1703,6 +1703,12 @@
 }
 
 
+void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
+  // TODO(hausner): implement this stub.
+  __ Branch(&StubCode::CallClosureFunctionLabel());
+}
+
+
 //  RA: return address (Dart code).
 //  S4: Arguments descriptor array.
 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 3db3c7e..692aa0e 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -307,6 +307,7 @@
 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp);
 
 
+// Used by eager and lazy deoptimization. Preserve result in RAX if necessary.
 // This stub translates optimized frame into unoptimized frame. The optimized
 // frame can contain values in registers and on stack, the unoptimized
 // frame contains all values on stack.
@@ -317,23 +318,26 @@
 // - Fill the unoptimized frame.
 // - Materialize objects that require allocation (e.g. Double instances).
 // GC can occur only after frame is fully rewritten.
-// Stack after EnterFrame(0) below:
+// Stack after EnterDartFrame(0) below:
 //   +------------------+
-//   | Saved FP         | <- TOS
+//   | PC marker        | <- TOS
+//   +------------------+
+//   | Saved FP         | <- FP of stub
 //   +------------------+
 //   | return-address   |  (deoptimization point)
 //   +------------------+
-//   | optimized frame  |
-//   |  ...             |
+//   | ...              | <- SP of optimized frame
 //
 // Parts of the code cannot GC, part of the code can GC.
 static void GenerateDeoptimizationSequence(Assembler* assembler,
-                                           bool preserve_rax) {
-  __ EnterFrame(0);
+                                           bool preserve_result) {
+  // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
+  __ EnterDartFrame(0);
   // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
-  const intptr_t saved_rax_offset_from_ebp = -(kNumberOfCpuRegisters - RAX);
-  // Result in EAX is preserved as part of pushing all registers below.
+  const intptr_t saved_result_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX);
+  // Result in RAX is preserved as part of pushing all registers below.
 
   // Push registers in their enumeration order: lowest register number at
   // lowest address.
@@ -351,41 +355,39 @@
   __ movq(RDI, RSP);  // Pass address of saved registers block.
   __ ReserveAlignedFrameSpace(0);
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry);
-  // Result (RAX) is stack-size (FP - SP) in bytes, incl. the return address.
+  // Result (RAX) is stack-size (FP - SP) in bytes.
 
-  if (preserve_rax) {
+  if (preserve_result) {
     // Restore result into RBX temporarily.
-    __ movq(RBX, Address(RBP, saved_rax_offset_from_ebp * kWordSize));
+    __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize));
   }
 
   __ LeaveFrame();
   __ popq(RCX);   // Preserve return address.
-  __ movq(RSP, RBP);
-  __ subq(RSP, RAX);
-  __ movq(Address(RSP, 0), RCX);
+  __ movq(RSP, RBP);  // Discard optimized frame.
+  __ subq(RSP, RAX);  // Reserve space for deoptimized frame.
+  __ pushq(RCX);  // Restore return address.
 
-  __ EnterFrame(0);
-  __ movq(RCX, RSP);  // Get last FP address.
-  if (preserve_rax) {
-    __ pushq(RBX);  // Preserve result.
+  // Leaf runtime function DeoptimizeFillFrame expects a Dart frame.
+  __ EnterDartFrame(0);
+  if (preserve_result) {
+    __ pushq(RBX);  // Preserve result as first local.
   }
   __ ReserveAlignedFrameSpace(0);
-  __ movq(RDI, RCX);  // Set up argument 1 last_fp.
+  __ movq(RDI, RBP);  // Pass last FP as parameter in RDI.
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry);
-  // Result (RAX) is our FP.
-  if (preserve_rax) {
+  if (preserve_result) {
     // Restore result into RBX.
-    __ movq(RBX, Address(RBP, -1 * kWordSize));
+    __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
   }
   // Code above cannot cause GC.
   __ LeaveFrame();
-  __ movq(RBP, RAX);
 
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
   __ EnterStubFrame();
-  if (preserve_rax) {
+  if (preserve_result) {
     __ pushq(RBX);  // Preserve result, it will be GC-d here.
   }
   __ pushq(Immediate(Smi::RawValue(0)));  // Space for the result.
@@ -394,7 +396,7 @@
   // of the bottom-most frame. They were used as materialization arguments.
   __ popq(RBX);
   __ SmiUntag(RBX);
-  if (preserve_rax) {
+  if (preserve_result) {
     __ popq(RAX);  // Restore result.
   }
   __ LeaveFrame();
@@ -1682,6 +1684,19 @@
   GenerateNArgsCheckInlineCacheStub(assembler, 1);
 }
 
+
+//  R10: Arguments descriptor array.
+//  TOS(0): return address (Dart code).
+void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ pushq(R10);       // Preserve arguments descriptor.
+  __ CallRuntime(kBreakpointClosureHandlerRuntimeEntry);
+  __ popq(R10);  // Restore arguments descriptor.
+  __ LeaveFrame();
+  __ jmp(&StubCode::CallClosureFunctionLabel());
+}
+
+
 //  R10: Arguments descriptor array.
 //  TOS(0): return address (Dart code).
 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index a4d4758..32a9850 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -848,6 +848,7 @@
     if (hasIsolateSupport()) {
       enqueuer.codegen.addToWorkList(
           isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE));
+      enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN));
     }
     if (enabledNoSuchMethod) {
       enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, noSuchMethodSelector);
@@ -872,6 +873,8 @@
       ClassElement cls = element;
       cls.ensureResolved(this);
       cls.forEachLocalMember(enqueuer.resolution.addToWorkList);
+      enqueuer.resolution.registerInstantiatedClass(
+          element, globalDependencies);
     } else {
       enqueuer.resolution.addToWorkList(element);
     }
@@ -951,7 +954,7 @@
     Node tree = parser.parse(element);
     validator.validate(tree);
     elements = resolver.resolve(element);
-    if (elements != null) {
+    if (elements != null && !analyzeSignaturesOnly) {
       // Only analyze nodes with a corresponding [TreeElements].
       checker.check(tree, elements);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 3cc71e4..4833202 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -79,7 +79,7 @@
 
   factory HTypeList.fromStaticInvocation(HInvokeStatic node) {
     bool allUnknown = true;
-    for (int i = 1; i < node.inputs.length; i++) {
+    for (int i = 0; i < node.inputs.length; i++) {
       if (node.inputs[i].instructionType != HType.UNKNOWN) {
         allUnknown = false;
         break;
@@ -87,9 +87,9 @@
     }
     if (allUnknown) return HTypeList.ALL_UNKNOWN;
 
-    HTypeList result = new HTypeList(node.inputs.length - 1);
+    HTypeList result = new HTypeList(node.inputs.length);
     for (int i = 0; i < result.types.length; i++) {
-      result.types[i] = node.inputs[i + 1].instructionType;
+      result.types[i] = node.inputs[i].instructionType;
       assert(!result.types[i].isConflicting());
     }
     return result;
@@ -647,7 +647,6 @@
   ClassElement jsNumberClass;
   ClassElement jsIntClass;
   ClassElement jsDoubleClass;
-  ClassElement jsFunctionClass;
   ClassElement jsNullClass;
   ClassElement jsBoolClass;
 
@@ -919,8 +918,6 @@
       jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')),
       jsNumberClass = compiler.findInterceptor(const SourceString('JSNumber')),
       jsNullClass = compiler.findInterceptor(const SourceString('JSNull')),
-      jsFunctionClass =
-          compiler.findInterceptor(const SourceString('JSFunction')),
       jsBoolClass = compiler.findInterceptor(const SourceString('JSBool')),
       jsMutableArrayClass =
           compiler.findInterceptor(const SourceString('JSMutableArray')),
@@ -1122,8 +1119,6 @@
     } else if (cls == compiler.doubleClass || cls == jsDoubleClass) {
       addInterceptors(jsDoubleClass, enqueuer, elements);
       addInterceptors(jsNumberClass, enqueuer, elements);
-    } else if (cls == compiler.functionClass || cls == jsFunctionClass) {
-      addInterceptors(jsFunctionClass, enqueuer, elements);
     } else if (cls == compiler.boolClass || cls == jsBoolClass) {
       addInterceptors(jsBoolClass, enqueuer, elements);
     } else if (cls == compiler.nullClass || cls == jsNullClass) {
@@ -1148,8 +1143,7 @@
 
   void registerUseInterceptor(Enqueuer enqueuer) {
     assert(!enqueuer.isResolutionQueue);
-    // TODO(9577): Make it so that these are not needed when there are no native
-    // classes.
+    if (!enqueuer.nativeEnqueuer.hasNativeClasses()) return;
     enqueuer.registerStaticUse(getNativeInterceptorMethod);
     enqueuer.registerStaticUse(defineNativeMethodsFinishMethod);
     enqueuer.registerStaticUse(initializeDispatchPropertyMethod);
@@ -1656,12 +1650,6 @@
       return typeCast
           ? const SourceString("boolTypeCast")
           : const SourceString('boolTypeCheck');
-    } else if (element == jsFunctionClass ||
-               element == compiler.functionClass) {
-      if (nativeCheckOnly) return null;
-      return typeCast
-          ? const SourceString("functionTypeCast")
-          : const SourceString('functionTypeCheck');
     } else if (element == jsIntClass || element == compiler.intClass) {
       if (nativeCheckOnly) return null;
       return typeCast ?
@@ -1845,7 +1833,6 @@
   ClassElement get growableListImplementation => jsExtendableArrayClass;
   ClassElement get mapImplementation => mapLiteralClass;
   ClassElement get constMapImplementation => constMapLiteralClass;
-  ClassElement get functionImplementation => jsFunctionClass;
   ClassElement get typeImplementation => typeLiteralClass;
   ClassElement get boolImplementation => jsBoolClass;
   ClassElement get nullImplementation => jsNullClass;
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 9397f1a..9273ad7 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -66,7 +66,8 @@
   }
 
   jsAst.Expression visitFunction(FunctionConstant constant) {
-    return new jsAst.VariableUse(namer.isolateAccess(constant.element));
+    return new jsAst.VariableUse(
+        namer.isolateStaticClosureAccess(constant.element));
   }
 
   jsAst.Expression visitNull(NullConstant constant) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index e9bb0f8..04c2515 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1759,6 +1759,10 @@
     // of stubs.
     ClassElement closureClass = compiler.closureClass;
     if (needsClosureClass && !instantiatedClasses.contains(closureClass)) {
+      ClassElement objectClass = compiler.objectClass;
+      if (!instantiatedClasses.contains(objectClass)) {
+        generateClass(objectClass, bufferForElement(objectClass, buffer));
+      }
       generateClass(closureClass, bufferForElement(closureClass, buffer));
     }
   }
@@ -1814,42 +1818,74 @@
     }
   }
 
+  final Map<Element, Element> staticGetters = new Map<Element, Element>();
+
   void emitStaticFunctionGetters(CodeBuffer eagerBuffer) {
+    for (FunctionElement element in
+             Elements.sortedByPosition(staticGetters.keys)) {
+      Element closure = staticGetters[element];
+      CodeBuffer buffer = bufferForElement(element, eagerBuffer);
+      String closureClass = namer.isolateAccess(closure);
+      String name = namer.getStaticClosureName(element);
+      String staticName = namer.getName(element);
+
+      String closureName = namer.getStaticClosureName(element);
+      jsAst.Node assignment = js('$isolateProperties.$name = '
+          'new $closureClass($isolateProperties.$staticName, "$closureName")');
+      buffer.write(jsAst.prettyPrint(assignment, compiler));
+      buffer.write('$N');
+    }
+  }
+
+  void emitStaticFunctionClosures() {
     Set<FunctionElement> functionsNeedingGetter =
         compiler.codegenWorld.staticFunctionsNeedingGetter;
     for (FunctionElement element in
              Elements.sortedByPosition(functionsNeedingGetter)) {
-      CodeBuffer buffer = bufferForElement(element, eagerBuffer);
+      String staticName = namer.getName(element);
+      String superName = namer.getName(compiler.closureClass);
+      String name = 'Closure\$${element.name.slowToString()}';
+      needsClosureClass = true;
 
-      // The static function 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.
+      ClassElement closureClassElement = new ClosureClassElement(
+          null, new SourceString(name), compiler, element,
+          element.getCompilationUnit());
+      // Now add the methods on the closure class. The instance method does not
+      // have the correct name. Since [addParameterStubs] use the name to create
+      // 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.closureInvocationSelectorName,
                                        element);
-      String staticName = namer.getName(element);
+
       String invocationName = namer.instanceMethodName(callElement);
-      String fieldAccess = '$isolateProperties.$staticName';
-      buffer.write("$fieldAccess.$invocationName$_=$_$fieldAccess$N");
+      String mangledName = namer.getName(closureClassElement);
 
-      addParameterStubs(callElement, (String name, jsAst.Expression value) {
-        jsAst.Expression assignment =
-            js('$isolateProperties.$staticName.$name = #', value);
-        buffer.write(jsAst.prettyPrint(assignment.toStatement(), compiler));
-        buffer.write('$N');
-      });
-
+      // Define the constructor with a name so that Object.toString can
+      // find the class name of the closure class.
+      ClassBuilder closureBuilder = new ClassBuilder();
       // 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.write('$fieldAccess.$fieldName$_=$_"$staticName"$N');
-      getTypedefChecksOn(element.computeType(compiler)).forEach(
-        (Element typedef) {
-          String operator = namer.operatorIs(typedef);
-          buffer.write('$fieldAccess.$operator$_=${_}true$N');
-        }
-      );
+      String methodName = namer.STATIC_CLOSURE_NAME_NAME;
+      emitBoundClosureClassHeader(
+          mangledName, superName, <String>[invocationName, methodName],
+          closureBuilder);
+
+      addParameterStubs(callElement, closureBuilder.addProperty);
+
+      DartType type = element.computeType(compiler);
+      getTypedefChecksOn(type).forEach((Element typedef) {
+        String operator = namer.operatorIs(typedef);
+        closureBuilder.addProperty(operator, js('true'));
+      });
+
+      // TODO(ngeoffray): Cache common base classes for clsures, bound
+      // closures, and static closures that have common type checks.
+      boundClosures.add(
+          js('$classesCollector.$mangledName = #',
+              closureBuilder.toObjectInitializer()));
+
+      staticGetters[element] = closureClassElement;
     }
   }
 
@@ -2353,15 +2389,10 @@
   String buildIsolateSetup(CodeBuffer buffer,
                            Element appMain,
                            Element isolateMain) {
-    String mainAccess = "${namer.isolateAccess(appMain)}";
+    String mainAccess = "${namer.isolateStaticClosureAccess(appMain)}";
     String currentIsolate = "${namer.CURRENT_ISOLATE}";
     // Since we pass the closurized version of the main method to
     // the isolate method, we must make sure that it exists.
-    if (!compiler.codegenWorld.staticFunctionsNeedingGetter.contains(appMain)) {
-      Selector selector = new Selector.callClosure(0);
-      String invocationName = namer.invocationName(selector);
-      buffer.write("$mainAccess.$invocationName = $mainAccess$N");
-    }
     return "${namer.isolateAccess(isolateMain)}($mainAccess)";
   }
 
@@ -2399,8 +2430,8 @@
       buffer.write(
           jsAst.prettyPrint(generateDispatchPropertyInitialization(),
                             compiler));
+      buffer.write(N);
     }
-    buffer.write(N);
     addComment('BEGIN invoke [main].', buffer);
     buffer.write("""
 if (typeof document !== "undefined" && document.readyState !== "complete") {
@@ -2453,8 +2484,6 @@
         condition = js('(typeof receiver) == "string"');
       } else if (cls == backend.jsNullClass) {
         condition = js('receiver == null');
-      } else if (cls == backend.jsFunctionClass) {
-        condition = js('(typeof receiver) == "function"');
       } else {
         throw 'internal error';
       }
@@ -2464,7 +2493,6 @@
     bool hasArray = false;
     bool hasBool = false;
     bool hasDouble = false;
-    bool hasFunction = false;
     bool hasInt = false;
     bool hasNull = false;
     bool hasNumber = false;
@@ -2477,7 +2505,6 @@
           cls == backend.jsExtendableArrayClass) hasArray = true;
       else if (cls == backend.jsBoolClass) hasBool = true;
       else if (cls == backend.jsDoubleClass) hasDouble = true;
-      else if (cls == backend.jsFunctionClass) hasFunction = true;
       else if (cls == backend.jsIntClass) hasInt = true;
       else if (cls == backend.jsNullClass) hasNull = true;
       else if (cls == backend.jsNumberClass) hasNumber = true;
@@ -2538,9 +2565,6 @@
       block.statements.add(js.if_('receiver == null',
                                   js.return_(js('receiver'))));
     }
-    if (hasFunction) {
-      block.statements.add(buildInterceptorCheck(backend.jsFunctionClass));
-    }
     if (hasBool) {
       block.statements.add(buildInterceptorCheck(backend.jsBoolClass));
     }
@@ -2920,7 +2944,8 @@
 
       if (!regularClasses.isEmpty ||
           !deferredClasses.isEmpty ||
-          !nativeClasses.isEmpty) {
+          !nativeClasses.isEmpty ||
+          !compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty) {
         // Shorten the code by using "$$" as temporary.
         classesCollector = r"$$";
         mainBuffer.add('var $classesCollector$_=$_{}$N$n');
@@ -2966,6 +2991,7 @@
         deferredBuffer.add("\$\$$_=${_}null$N$n");
       }
 
+      emitStaticFunctionClosures();
       emitClosureClassIfNeeded(mainBuffer);
 
       addComment('Bound closures', mainBuffer);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index ea9a82f..3f43bc6 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -545,7 +545,6 @@
       if (cls == backend.jsIntClass) return "i";
       if (cls == backend.jsNumberClass) return "n";
       if (cls == backend.jsNullClass) return "u";
-      if (cls == backend.jsFunctionClass) return "f";
       if (cls == backend.jsBoolClass) return "b";
       if (cls == backend.jsInterceptorClass) return "I";
       return cls.name.slowToString();
@@ -735,6 +734,11 @@
     return getMappedGlobalName("$getterPrefix${getName(element)}");
   }
 
+  String getStaticClosureName(Element element) {
+    assert(Elements.isStaticOrTopLevelFunction(element));
+    return getMappedGlobalName("${getName(element)}\$closure");
+  }
+
   String isolatePropertiesAccess(Element element) {
     return "$isolateName.$isolatePropertiesName.${getName(element)}";
   }
@@ -752,6 +756,10 @@
     return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}";
   }
 
+  String isolateStaticClosureAccess(Element element) {
+    return "$CURRENT_ISOLATE.${getStaticClosureName(element)}";
+  }
+
   String operatorIsPrefix() => r'$is';
 
   String operatorAsPrefix() => r'$as';
diff --git a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
index 4f2b76d..927e82a 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
@@ -287,17 +287,6 @@
 }
 
 /**
- * The interceptor class for tear-off static methods. Unlike
- * tear-off instance methods, tear-off static methods are just the JS
- * function, and methods inherited from Object must therefore be
- * intercepted.
- */
-class JSFunction extends Interceptor implements Function {
-  const JSFunction();
-  String toString() => 'Closure';
-}
-
-/**
  * The interceptor class for [bool].
  */
 class JSBool extends Interceptor implements bool {
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
index a31da57..bc7ea75 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
@@ -56,6 +56,12 @@
   }
 }
 
+patch class FileStat {
+  patch static List<int> _statSync(String path) {
+    throw new UnsupportedError("FileStat.stat");
+  }
+}
+
 patch class FileSystemEntity {
   patch static _getType(String path, bool followLinks) {
     throw new UnsupportedError("FileSystemEntity._getType");
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
index cf639f2..ebbb9fd 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
@@ -73,7 +73,7 @@
  * call is not emitted.
  */
 void startRootIsolate(entry) {
-  _globalState = new _Manager();
+  _globalState = new _Manager(entry);
 
   // Don't start the main loop again, if we are in a worker.
   if (_globalState.isWorker) return;
@@ -188,7 +188,10 @@
   /** Registry of active [_ManagerStub]s.  Only used in the main [_Manager]. */
   Map<int, _ManagerStub> managers;
 
-  _Manager() {
+  /** The entry point given by [startRootIsolate]. */
+  final Function entry;
+
+  _Manager(this.entry) {
     _nativeDetectEnvironment();
     topEventLoop = new _EventLoop();
     isolates = new Map<int, _IsolateContext>();
@@ -504,7 +507,10 @@
     switch (msg['command']) {
       case 'start':
         _globalState.currentManagerId = msg['id'];
-        Function entryPoint = _getJSFunctionFromName(msg['functionName']);
+        String functionName = msg['functionName'];
+        Function entryPoint = (functionName == null)
+            ? _globalState.entry
+            : _getJSFunctionFromName(functionName);
         var replyTo = _deserializeMessage(msg['replyTo']);
         var context = new _IsolateContext();
         _globalState.topEventLoop.enqueue(context, () {
@@ -668,7 +674,6 @@
    * name for the isolate entry point class.
    */
   static void _spawnWorker(functionName, uri, replyPort) {
-    if (functionName == null) functionName = 'main';
     if (uri == null) uri = thisScript;
     final worker = _newWorker(uri);
     worker.onmessage = JS('',
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index 290385f..8ac68cd 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -1094,18 +1094,6 @@
       Primitives.objectTypeName(value), 'bool');
 }
 
-functionTypeCheck(value) {
-  if (value == null) return value;
-  if (value is Function) return value;
-  throw new TypeErrorImplementation(value, 'Function');
-}
-
-functionTypeCast(value) {
-  if (value is Function || value == null) return value;
-  throw new CastErrorImplementation(
-      Primitives.objectTypeName(value), 'Function');
-}
-
 intTypeCheck(value) {
   if (value == null) return value;
   if (value is int) return value;
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 2b70c53..627055d 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -55,6 +55,9 @@
 
   NativeBehavior getNativeBehaviorOf(Send node) => NativeBehavior.NONE;
 
+  /// Returns whether native classes are being used.
+  bool hasNativeClasses() => false;
+
   /**
    * Handles JS-calls, which can be an instantiation point for types.
    *
@@ -84,6 +87,8 @@
   final Set<ClassElement> pendingClasses = new Set<ClassElement>();
   final Set<ClassElement> unusedClasses = new Set<ClassElement>();
 
+  bool hasNativeClasses() => !registeredClasses.isEmpty;
+
   /**
    * Records matched constraints ([SpecialType] or [DartType]).  Once a type
    * constraint has been matched, there is no need to match it again.
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 487104c..df17528 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -1193,6 +1193,14 @@
     if (canBeInlined == false) return false;
     if (!selector.applies(function, compiler)) return false;
 
+    // Don't inline operator== methods if the parameter can be null.
+    if (element.name == const SourceString('==')) {
+      if (element.getEnclosingClass() != compiler.objectClass
+          && providedArguments[1].canBeNull()) {
+        return false;
+      }
+    }
+
     FunctionExpression functionExpression = function.parseNode(compiler);
     TreeElements newElements =
         compiler.enqueuer.resolution.getCachedElements(function);
@@ -2434,9 +2442,7 @@
       }
     }
 
-    HInvokeDynamicMethod result =
-        buildInvokeDynamic(node, elements.getSelector(node), [operand]);
-    pushWithPosition(result, node);
+    pushInvokeDynamic(node, elements.getSelector(node), [operand]);
   }
 
   void visitBinary(HInstruction left,
@@ -2455,9 +2461,7 @@
         return;
     }
 
-    pushWithPosition(
-          buildInvokeDynamic(send, selector, [left, right]),
-          op);
+    pushInvokeDynamic(send, selector, [left, right], location: op);
     if (op.source.stringValue == '!=') {
       pushWithPosition(new HNot(popBoolified()), op);
     }
@@ -2489,8 +2493,7 @@
                                                   HInstruction receiver) {
     assert(Elements.isInstanceSend(send, elements));
     assert(selector.isGetter());
-    HInstruction res = buildInvokeDynamic(send, selector, [receiver]);
-    pushWithPosition(res, send);
+    pushInvokeDynamic(send, selector, [receiver]);
   }
 
   void generateGetter(Send send, Element element) {
@@ -2516,14 +2519,12 @@
             return;
           }
         }
-        // TODO(5346): Try to avoid the need for calling [declaration] before
-        // creating an [HStatic].
-        HInstruction instruction = new HStatic(element.declaration);
         if (element.isGetter()) {
-          add(instruction);
-          instruction = buildInvokeStatic(<HInstruction>[instruction]);
-          push(instruction);
+          push(buildInvokeStatic(element, <HInstruction>[]));
         } else {
+          // TODO(5346): Try to avoid the need for calling [declaration] before
+          // creating an [HStatic].
+          HInstruction instruction = new HStatic(element.declaration);
           instruction.instructionType =
               new HType.inferredTypeForElement(element, compiler);
           push(instruction);
@@ -2564,9 +2565,8 @@
       location = send;
     }
     assert(selector.isSetter());
-    HInstruction res = buildInvokeDynamic(
-        location, selector, [receiver, value]);
-    addWithPosition(res, location);
+    pushInvokeDynamic(location, selector, [receiver, value]);
+    pop();
     stack.add(value);
   }
 
@@ -2581,10 +2581,8 @@
     }
     if (Elements.isStaticOrTopLevelField(element)) {
       if (element.isSetter()) {
-        HStatic target = new HStatic(element);
-        add(target);
-        var instruction = buildInvokeStatic(
-            <HInstruction>[target, value], HType.UNKNOWN);
+        var instruction = buildInvokeStatic(element,
+            <HInstruction>[value], HType.UNKNOWN);
         addWithPosition(instruction, location);
       } else {
         value = potentiallyCheckType(value, element.computeType(compiler));
@@ -2621,27 +2619,21 @@
   }
 
   void pushInvokeHelper0(Element helper, HType type) {
-    HInstruction reference = new HStatic(helper);
-    add(reference);
-    List<HInstruction> inputs = <HInstruction>[reference];
-    push(buildInvokeStatic(inputs, type));
+    List<HInstruction> inputs = <HInstruction>[];
+    push(buildInvokeStatic(helper, inputs, type));
   }
 
   void pushInvokeHelper1(Element helper, HInstruction a0, HType type) {
-    HInstruction reference = new HStatic(helper);
-    add(reference);
-    List<HInstruction> inputs = <HInstruction>[reference, a0];
-    push(buildInvokeStatic(inputs, type));
+    List<HInstruction> inputs = <HInstruction>[a0];
+    push(buildInvokeStatic(helper, inputs, type));
   }
 
   void pushInvokeHelper2(Element helper,
                          HInstruction a0,
                          HInstruction a1,
                          HType type) {
-    HInstruction reference = new HStatic(helper);
-    add(reference);
-    List<HInstruction> inputs = <HInstruction>[reference, a0, a1];
-    push(buildInvokeStatic(inputs, type));
+    List<HInstruction> inputs = <HInstruction>[a0, a1];
+    push(buildInvokeStatic(helper, inputs, type));
   }
 
   void pushInvokeHelper3(Element helper,
@@ -2649,10 +2641,8 @@
                          HInstruction a1,
                          HInstruction a2,
                          HType type) {
-    HInstruction reference = new HStatic(helper);
-    add(reference);
-    List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2];
-    push(buildInvokeStatic(inputs, type));
+    List<HInstruction> inputs = <HInstruction>[a0, a1, a2];
+    push(buildInvokeStatic(helper, inputs, type));
   }
 
   void pushInvokeHelper4(Element helper,
@@ -2661,10 +2651,8 @@
                          HInstruction a2,
                          HInstruction a3,
                          HType type) {
-    HInstruction reference = new HStatic(helper);
-    add(reference);
-    List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3];
-    push(buildInvokeStatic(inputs, type));
+    List<HInstruction> inputs = <HInstruction>[a0, a1, a2, a3];
+    push(buildInvokeStatic(helper, inputs, type));
   }
 
   void pushInvokeHelper5(Element helper,
@@ -2674,10 +2662,8 @@
                          HInstruction a3,
                          HInstruction a4,
                          HType type) {
-    HInstruction reference = new HStatic(helper);
-    add(reference);
-    List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3, a4];
-    push(buildInvokeStatic(inputs, type));
+    List<HInstruction> inputs = <HInstruction>[a0, a1, a2, a3, a4];
+    push(buildInvokeStatic(helper, inputs, type));
   }
 
   HForeign createForeign(String code,
@@ -2776,19 +2762,14 @@
     if (type.kind == TypeKind.TYPE_VARIABLE) {
       HInstruction runtimeType = addTypeVariableReference(type);
       Element helper = backend.getGetObjectIsSubtype();
-      HInstruction helperCall = new HStatic(helper);
-      add(helperCall);
-      List<HInstruction> inputs = <HInstruction>[helperCall, expression,
-                                                 runtimeType];
-      HInstruction call = buildInvokeStatic(inputs, HType.BOOLEAN);
+      List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
+      HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN);
       add(call);
       instruction = new HIs(type, <HInstruction>[expression, call],
                             HIs.VARIABLE_CHECK);
     } else if (RuntimeTypes.hasTypeArguments(type)) {
       Element element = type.element;
       Element helper = backend.getCheckSubtype();
-      HInstruction helperCall = new HStatic(helper);
-      add(helperCall);
       HInstruction representations =
         buildTypeArgumentRepresentations(type);
       add(representations);
@@ -2799,12 +2780,11 @@
       // have a subclass.
       HInstruction asFieldName =
           addConstantString(node, backend.namer.substitutionName(element));
-      List<HInstruction> inputs = <HInstruction>[helperCall,
-                                                 expression,
+      List<HInstruction> inputs = <HInstruction>[expression,
                                                  isFieldName,
                                                  representations,
                                                  asFieldName];
-      HInstruction call = buildInvokeStatic(inputs, HType.BOOLEAN);
+      HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN);
       add(call);
       instruction = new HIs(type, <HInstruction>[expression, call],
                             HIs.COMPOUND_CHECK);
@@ -2901,14 +2881,7 @@
     }
   }
 
-  bool isThisSend(Send send) {
-    Node receiver = send.receiver;
-    if (receiver == null) return true;
-    Identifier identifier = receiver.asIdentifier();
-    return identifier != null && identifier.isThis();
-  }
-
-  visitDynamicSend(Send node, {bool inline: true}) {
+  visitDynamicSend(Send node) {
     Selector selector = elements.getSelector(node);
 
     List<HInstruction> inputs = <HInstruction>[];
@@ -2916,47 +2889,11 @@
     inputs.add(receiver);
     addDynamicSendArgumentsToList(node, inputs);
 
-    // We prefer to not inline certain operations on indexables,
-    // because the constant folder will handle them better and turn
-    // them into simpler instructions that allow further
-    // optimizations.
-    bool isOptimizableOperationOnIndexable(Selector selector, Element element) {
-      bool isLength = selector.isGetter()
-          && selector.name == const SourceString("length");
-      if (isLength || selector.isIndex()) {
-        DartType classType = element.getEnclosingClass().computeType(compiler);
-        HType type = new HType.nonNullExact(classType, compiler);
-        return type.isIndexable(compiler);
-      } else if (selector.isIndexSet()) {
-        DartType classType = element.getEnclosingClass().computeType(compiler);
-        HType type = new HType.nonNullExact(classType, compiler);
-        return type.isMutableIndexable(compiler);
-      } else {
-        return false;
-      }
+    pushInvokeDynamic(node, selector, inputs);
+    if (selector.isSetter() || selector.isIndexSet()) {
+      pop();
+      stack.add(inputs.last);
     }
-
-    Element element = compiler.world.locateSingleElement(selector);
-    // TODO(ngeoffray): If [element] is a getter, then this send is
-    // a closure send. We should teach that to [ResolvedVisitor].
-    if (inline
-        && element != null
-        && !element.isGetter()
-        // This check is to ensure we don't regress compared to our
-        // previous limited inlining. We currently don't want to
-        // inline methods on intercepted classes because the
-        // optimizers apply their own optimizations on these methods.
-        && (!backend.interceptedClasses.contains(element.getEnclosingClass())
-            || isThisSend(node))
-        // Avoid inlining optimizable operations on indexables.
-        && !isOptimizableOperationOnIndexable(selector, element)) {
-      if (tryInlineMethod(element, selector, node.arguments, inputs, node)) {
-        return;
-      }
-    }
-
-    HInstruction invoke = buildInvokeDynamic(node, selector, inputs);
-    pushWithPosition(invoke, node);
   }
 
   visitClosureSend(Send node) {
@@ -3042,11 +2979,9 @@
         compiler.cancel(
             'Isolate library and compiler mismatch', node: node);
       }
-      HStatic target = new HStatic(element);
-      add(target);
-      List<HInstruction> inputs = <HInstruction>[target];
+      List<HInstruction> inputs = <HInstruction>[];
       addGenericSendArgumentsToList(link, inputs);
-      push(buildInvokeStatic(inputs, HType.UNKNOWN));
+      push(buildInvokeStatic(element, inputs, HType.UNKNOWN));
     }
   }
 
@@ -3345,10 +3280,8 @@
 
     // Set the runtime type information on the object.
     Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo();
-    HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement);
-    add(typeInfoSetter);
-    add(buildInvokeStatic(
-        <HInstruction>[typeInfoSetter, newObject, typeInfo], HType.UNKNOWN));
+    add(buildInvokeStatic(typeInfoSetterElement,
+        <HInstruction>[newObject, typeInfo], HType.UNKNOWN));
   }
 
   /**
@@ -3402,12 +3335,7 @@
                        message: 'Constructor Symbol.validated is missing'));
     }
 
-    // TODO(5346): Try to avoid the need for calling [declaration] before
-    // creating an [HStatic].
-    HInstruction target = new HStatic(constructor.declaration);
-    add(target);
     var inputs = <HInstruction>[];
-    inputs.add(target);
     // TODO(5347): Try to avoid the need for calling [implementation] before
     // calling [addStaticSendArgumentsToList].
     bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
@@ -3441,7 +3369,8 @@
       compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements);
     }
     HType elementType = computeType(constructor);
-    HInstruction newInstance = buildInvokeStatic(inputs, elementType);
+    HInstruction newInstance =
+        buildInvokeStatic(constructor, inputs, elementType);
     pushWithPosition(newInstance, node);
 
     // The List constructor forwards to a Dart static method that does
@@ -3480,9 +3409,7 @@
         return;
       }
 
-      HInstruction target = new HStatic(element);
-      add(target);
-      var inputs = <HInstruction>[target];
+      var inputs = <HInstruction>[];
       // TODO(5347): Try to avoid the need for calling [implementation] before
       // calling [addStaticSendArgumentsToList].
       bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
@@ -3494,11 +3421,12 @@
       }
 
       if (isIdenticalFunction) {
-        pushWithPosition(new HIdentity(inputs[1], inputs[2]), node);
+        pushWithPosition(new HIdentity(inputs[0], inputs[1]), node);
         return;
       }
 
-      HInvokeStatic instruction = buildInvokeStatic(inputs, HType.UNKNOWN);
+      HInvokeStatic instruction =
+          buildInvokeStatic(element, inputs, HType.UNKNOWN);
       HType returnType =
           new HType.inferredReturnTypeForElement(element, compiler);
       if (returnType.isUnknown()) {
@@ -3691,9 +3619,61 @@
     }
   }
 
-  HInstruction buildInvokeDynamic(Node node,
-                                  Selector selector,
-                                  List<HInstruction> arguments) {
+  void pushInvokeDynamic(Node node,
+                         Selector selector,
+                         List<HInstruction> arguments,
+                         {Node location}) {
+    if (location == null) location = node;
+
+    // We prefer to not inline certain operations on indexables,
+    // because the constant folder will handle them better and turn
+    // them into simpler instructions that allow further
+    // optimizations.
+    bool isOptimizableOperationOnIndexable(Selector selector, Element element) {
+      bool isLength = selector.isGetter()
+          && selector.name == const SourceString("length");
+      if (isLength || selector.isIndex()) {
+        DartType classType = element.getEnclosingClass().computeType(compiler);
+        HType type = new HType.nonNullExact(classType, compiler);
+        return type.isIndexable(compiler);
+      } else if (selector.isIndexSet()) {
+        DartType classType = element.getEnclosingClass().computeType(compiler);
+        HType type = new HType.nonNullExact(classType, compiler);
+        return type.isMutableIndexable(compiler);
+      } else {
+        return false;
+      }
+    }
+
+    bool isThisSend(Send send) {
+      if (send.isPrefix || send.isPostfix) return false;
+      Node receiver = send.receiver;
+      if (receiver == null) return true;
+      Identifier identifier = receiver.asIdentifier();
+      return identifier != null && identifier.isThis();
+    }
+
+    Element element = compiler.world.locateSingleElement(selector);
+    if (element != null
+        // TODO(ngeoffray): Handle non-send nodes.
+        && (node.asSend() != null)
+        && !(element.isGetter() && selector.isCall())
+        && !(element.isFunction() && selector.isGetter())
+        // This check is to ensure we don't regress compared to our
+        // previous limited inlining. We currently don't want to
+        // inline methods on intercepted classes because the
+        // optimizers apply their own optimizations on these methods.
+        && (!backend.interceptedClasses.contains(element.getEnclosingClass())
+            || isThisSend(node))
+        // Avoid inlining optimizable operations on indexables.
+        && !isOptimizableOperationOnIndexable(selector, element)) {
+      Send send = node.asSend();
+      Link<Node> nodes = send.isPropertyAccess ? null : send.arguments;
+      if (tryInlineMethod(element, selector, nodes, arguments, node)) {
+        return;
+      }
+    }
+
     HInstruction receiver = arguments[0];
     Set<ClassElement> interceptedClasses =
         backend.getInterceptedClassesOn(selector.name);
@@ -3706,23 +3686,31 @@
     inputs.addAll(arguments);
     if (selector.isGetter()) {
       bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
-      return new HInvokeDynamicGetter(selector, null, inputs, !hasGetter);
+      pushWithPosition(
+          new HInvokeDynamicGetter(selector, null, inputs, !hasGetter),
+          location);
     } else if (selector.isSetter()) {
       bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
-      return new HInvokeDynamicSetter(selector, null, inputs, !hasSetter);
+      pushWithPosition(
+          new HInvokeDynamicSetter(selector, null, inputs, !hasSetter),
+          location);
     } else {
-      return new HInvokeDynamicMethod(selector, inputs, isIntercepted);
+      pushWithPosition(
+          new HInvokeDynamicMethod(selector, inputs, isIntercepted),
+          location);
     }
   }
 
-  HInstruction buildInvokeStatic(List<HInstruction> inputs,
+  HInstruction buildInvokeStatic(Element element,
+                                 List<HInstruction> inputs,
                                  [HType type = null]) {
-    HStatic staticInstruction = inputs[0];
-    Element element = staticInstruction.element;
     if (type == null) {
       type = new HType.inferredReturnTypeForElement(element, compiler);
     }
-    HInstruction instruction = new HInvokeStatic(inputs, type);
+    // TODO(5346): Try to avoid the need for calling [declaration] before
+    // creating an [HInvokeStatic].
+    HInstruction instruction =
+        new HInvokeStatic(element.declaration, inputs, type);
     instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
     return instruction;
   }
@@ -3733,9 +3721,7 @@
     HInstruction receiver = localsHandler.readThis();
     // TODO(5346): Try to avoid the need for calling [declaration] before
     // creating an [HStatic].
-    HInstruction target = new HStatic(element.declaration);
-    add(target);
-    List<HInstruction> inputs = <HInstruction>[target];
+    List<HInstruction> inputs = <HInstruction>[];
     Set<ClassElement> interceptedClasses =
         backend.getInterceptedClassesOn(selector.name);
     if (interceptedClasses != null) {
@@ -3744,6 +3730,7 @@
     inputs.add(receiver);
     inputs.addAll(arguments);
     HInstruction instruction = new HInvokeSuper(
+        element,
         currentNonClosureClass,
         inputs,
         isSetter: selector.isSetter() || selector.isIndexSet());
@@ -3832,12 +3819,7 @@
       stack.add(result);
     } else if (node.isIndex) {
       if (const SourceString("=") == op.source) {
-        // TODO(kasperl): We temporarily disable inlining because the
-        // code here cannot deal with it yet.
-        visitDynamicSend(node, inline: false);
-        HInvokeDynamicMethod method = pop();
-        // Push the value.
-        stack.add(method.inputs.last);
+        visitDynamicSend(node);
       } else {
         visit(node.receiver);
         HInstruction receiver = pop();
@@ -3849,18 +3831,18 @@
           index = pop();
         }
 
-        HInvokeDynamicMethod getterInstruction = buildInvokeDynamic(
+        pushInvokeDynamic(
             node,
             elements.getGetterSelectorInComplexSendSet(node),
             [receiver, index]);
-        add(getterInstruction);
+        HInstruction getterInstruction = pop();
 
         handleComplexOperatorSend(node, getterInstruction, arguments);
         HInstruction value = pop();
 
-        HInvokeDynamicMethod assign = buildInvokeDynamic(
+        pushInvokeDynamic(
             node, elements.getSelector(node), [receiver, index, value]);
-        add(assign);
+        pop();
 
         if (node.isPostfix) {
           stack.add(getterInstruction);
@@ -4151,17 +4133,17 @@
       Selector selector = compiler.iteratorSelector;
       visit(node.expression);
       HInstruction receiver = pop();
-      iterator = buildInvokeDynamic(node, selector, [receiver]);
-      add(iterator);
+      pushInvokeDynamic(node, selector, [receiver]);
+      iterator = pop();
     }
     HInstruction buildCondition() {
       Selector selector = compiler.moveNextSelector;
-      push(buildInvokeDynamic(node, selector, [iterator]));
+      pushInvokeDynamic(node, selector, [iterator]);
       return popBoolified();
     }
     void buildBody() {
       Selector call = compiler.currentSelector;
-      push(buildInvokeDynamic(node, call, [iterator]));
+      pushInvokeDynamic(node, call, [iterator]);
 
       Node identifier = node.declaredIdentifier;
       Element variable = elements[identifier];
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 924ed88..9a3cd73 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -527,10 +527,11 @@
   /**
     * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET].
     */
-  List<js.Expression> visitArguments(List<HInstruction> inputs) {
-    assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET);
+  List<js.Expression> visitArguments(List<HInstruction> inputs,
+                                     {int start: HInvoke.ARGUMENTS_OFFSET}) {
+    assert(inputs.length >= start);
     List<js.Expression> result = <js.Expression>[];
-    for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) {
+    for (int i = start; i < inputs.length; i++) {
       use(inputs[i]);
       result.add(pop());
     }
@@ -1612,18 +1613,26 @@
       // Register this invocation to collect the types used at all call sites.
       backend.registerStaticInvocation(node);
     }
-    use(node.target);
-    push(new js.Call(pop(), visitArguments(node.inputs)), node);
+    Element element = node.element;
+    world.registerStaticUse(element);
+    ClassElement cls = element.getEnclosingClass();
+    if (element.isGenerativeConstructor()
+        || (element.isFactoryConstructor() && cls == compiler.listClass)) {
+      world.registerInstantiatedClass(cls, work.resolutionTree);
+    }
+    push(new js.VariableUse(backend.namer.isolateAccess(node.element)));
+    push(new js.Call(pop(), visitArguments(node.inputs, start: 0)), node);
   }
 
   visitInvokeSuper(HInvokeSuper node) {
     Element superMethod = node.element;
+    world.registerStaticUse(superMethod);
     Element superClass = superMethod.getEnclosingClass();
     if (superMethod.kind == ElementKind.FIELD) {
       String fieldName = node.caller.isShadowedByField(superMethod)
           ? backend.namer.shadowedFieldName(superMethod)
           : backend.namer.instanceFieldName(superMethod);
-      use(node.inputs[1]);
+      use(node.inputs[0]);
       js.PropertyAccess access =
           new js.PropertyAccess.field(pop(), fieldName);
       if (node.isSetter) {
@@ -1640,7 +1649,8 @@
           new js.PropertyAccess.field(classReference, "prototype");
       js.PropertyAccess method =
           new js.PropertyAccess.field(prototype, methodName);
-      push(jsPropertyCall(method, "call", visitArguments(node.inputs)), node);
+      push(jsPropertyCall(
+          method, "call", visitArguments(node.inputs, start: 0)), node);
     }
     world.registerStaticUse(superMethod);
   }
@@ -1988,27 +1998,17 @@
   }
 
   void visitStatic(HStatic node) {
-    // Check whether this static is used for anything else than as a target in
-    // a static call.
-    node.usedBy.forEach((HInstruction instr) {
-      if (instr is !HInvokeStatic) {
-        backend.registerNonCallStaticUse(node);
-        if (node.element.isFunction()) {
-          world.registerInstantiatedClass(
-              compiler.functionClass, work.resolutionTree);
-        }
-      } else if (instr.target != node) {
-        backend.registerNonCallStaticUse(node);
-      }
-    });
     Element element = node.element;
-    world.registerStaticUse(element);
-    ClassElement cls = element.getEnclosingClass();
-    if (element.isGenerativeConstructor()
-        || (element.isFactoryConstructor() && cls == compiler.listClass)) {
-      world.registerInstantiatedClass(cls, work.resolutionTree);
+    if (element.isFunction()) {
+      backend.registerNonCallStaticUse(node);
+      world.registerInstantiatedClass(
+          compiler.functionClass, work.resolutionTree);
+      push(new js.VariableUse(
+          backend.namer.isolateStaticClosureAccess(node.element)));
+    } else {
+      push(new js.VariableUse(backend.namer.isolateAccess(node.element)));
     }
-    push(new js.VariableUse(backend.namer.isolateAccess(node.element)));
+    world.registerStaticUse(element);
   }
 
   void visitLazyStatic(HLazyStatic node) {
@@ -2182,21 +2182,6 @@
     push(new js.Binary('!=', pop(), new js.LiteralNull()));
   }
 
-  void checkFunction(HInstruction input,
-                     DartType type,
-                     { bool negative: false}) {
-    String relation = negative ? '!==' : '===';
-    checkTypeOf(input, relation, 'function');
-    js.Expression functionTest = pop();
-    checkObject(input, relation);
-    js.Expression objectTest = pop();
-    checkType(input, type, negative: negative);
-    String combiner = negative ? '||' : '&&';
-    push(new js.Binary(negative ? '&&' : '||',
-                       functionTest,
-                       new js.Binary(combiner, objectTest, pop())));
-  }
-
   void checkType(HInstruction input, DartType type, {bool negative: false}) {
     assert(invariant(input, !type.isMalformed,
                      message: 'Attempt to check malformed type $type'));
@@ -2338,9 +2323,6 @@
       } else if (element == compiler.boolClass) {
         checkBool(input, relation);
         attachLocationToLast(node);
-      } else if (element == compiler.functionClass) {
-        checkFunction(input, type, negative: negative);
-        attachLocationToLast(node);
       } else if (element == compiler.intClass) {
         // The is check in the code tells us that it might not be an
         // int. So we do a typeof first to avoid possible
@@ -2488,6 +2470,12 @@
 
       assert(node.isCheckedModeCheck || node.isCastTypeCheck);
       DartType type = node.typeExpression;
+      if (type.kind == TypeKind.FUNCTION) {
+        // TODO(5022): We currently generate $isFunction checks for
+        // function types.
+        world.registerIsCheck(
+            compiler.functionClass.computeType(compiler), work.resolutionTree);
+      }
       world.registerIsCheck(type, work.resolutionTree);
 
       // TODO(kasperl): For now, we ignore type checks against type
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
index 985a7a3..d1f80ec 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -21,7 +21,7 @@
 
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
-    return instruction.instructionType;
+    return HType.UNKNOWN;
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
@@ -164,7 +164,7 @@
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
     if (instruction.inputs[1].isPrimitive()) return HType.INTEGER;
-    return instruction.instructionType;
+    return HType.UNKNOWN;
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
@@ -200,7 +200,7 @@
                                   Compiler compiler) {
     HType operandType = instruction.inputs[1].instructionType;
     if (operandType.isNumber()) return operandType;
-    return instruction.instructionType;
+    return HType.UNKNOWN;
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
@@ -223,7 +223,7 @@
       if (left.isDouble() || right.isDouble()) return HType.DOUBLE;
       return HType.NUMBER;
     }
-    return instruction.instructionType;
+    return HType.UNKNOWN;
   }
 
   HType computeDesiredTypeForInput(HInvokeDynamic instruction,
@@ -301,7 +301,7 @@
                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     if (left.isNumber()) return HType.DOUBLE;
-    return instruction.instructionType;
+    return HType.UNKNOWN;
   }
 
   HType computeDesiredTypeForInput(HInstruction instruction,
@@ -381,7 +381,7 @@
     // integer or throw an error.
     HInstruction left = instruction.inputs[1];
     if (left.isPrimitive()) return HType.INTEGER;
-    return instruction.instructionType;
+    return HType.UNKNOWN;
   }
 
   HType computeDesiredTypeForInput(HInvokeDynamic instruction,
@@ -486,7 +486,7 @@
     if (instruction.inputs[1].instructionType.isPrimitiveOrNull()) {
       return HType.BOOLEAN;
     }
-    return instruction.instructionType;
+    return HType.UNKNOWN;
   }
 
   HType computeDesiredTypeForInput(HInvokeDynamic instruction,
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 727bcc9..7dccbc9 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -1354,16 +1354,15 @@
 }
 
 class HInvokeStatic extends HInvoke {
+  final Element element;
   /** The first input must be the target. */
-  HInvokeStatic(inputs, HType type) : super(inputs) {
+  HInvokeStatic(this.element, inputs, HType type) : super(inputs) {
     instructionType = type;
   }
 
   toString() => 'invoke static: ${element.name}';
   accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
   int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;
-  Element get element => target.element;
-  HStatic get target => inputs[0];
 }
 
 class HInvokeSuper extends HInvokeStatic {
@@ -1371,15 +1370,15 @@
   final ClassElement caller;
   final bool isSetter;
 
-  HInvokeSuper(this.caller, inputs, {this.isSetter})
-      : super(inputs, HType.UNKNOWN);
+  HInvokeSuper(Element element, this.caller, inputs, {this.isSetter})
+      : super(element, inputs, HType.UNKNOWN);
   toString() => 'invoke super: ${element.name}';
   accept(HVisitor visitor) => visitor.visitInvokeSuper(this);
 
   HInstruction get value {
     assert(isSetter);
-    // Index 0: the element, index 1: 'this'.
-    return inputs[2];
+    // Index 0: 'this'.
+    return inputs[1];
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index c16dcef..2d9c62a 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -627,15 +627,15 @@
         // Try to recognize the length getter with input
         // [:new List(int):].
         HInvokeStatic call = node.receiver;
-        Element element = call.target.element;
+        Element element = call.element;
         // TODO(ngeoffray): checking if the second input is an integer
         // should not be necessary but it currently makes it easier for
         // other optimizations to reason about a fixed length constructor
         // that we know takes an int.
         if (element == compiler.unnamedListConstructor
-            && call.inputs.length == 2
-            && call.inputs[1].isInteger()) {
-          return call.inputs[1];
+            && call.inputs.length == 1
+            && call.inputs[0].isInteger()) {
+          return call.inputs[0];
         }
       } else if (node.receiver.isConstantList() ||
                  node.receiver.isConstantString()) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index 740d0f9..f11f5d5 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -354,14 +354,14 @@
       => visitInvokeDynamic(node, "set");
 
   String visitInvokeStatic(HInvokeStatic invoke) {
-    String target = temporaryId(invoke.target);
+    String target = invoke.element.name.slowToString();
     int offset = HInvoke.ARGUMENTS_OFFSET;
     List arguments = invoke.inputs.sublist(offset);
     return visitGenericInvoke("Invoke", target, arguments);
   }
 
   String visitInvokeSuper(HInvokeSuper invoke) {
-    String target = temporaryId(invoke.target);
+    String target = invoke.element.name.slowToString();
     int offset = HInvoke.ARGUMENTS_OFFSET + 1;
     List arguments = invoke.inputs.sublist(offset);
     return visitGenericInvoke("Invoke super", target, arguments);
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 9272289..24faf77 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -8,31 +8,15 @@
   TypeCheckerTask(Compiler compiler) : super(compiler);
   String get name => "Type checker";
 
-  static const bool LOG_FAILURES = false;
-
   void check(Node tree, TreeElements elements) {
     measure(() {
       Visitor visitor =
           new TypeCheckerVisitor(compiler, elements, compiler.types);
-      try {
-        tree.accept(visitor);
-      } on CancelTypeCheckException catch (e) {
-        if (LOG_FAILURES) {
-          // Do not warn about unimplemented features; log message instead.
-          compiler.log("'${e.node}': ${e.reason}");
-        }
-      }
+      tree.accept(visitor);
     });
   }
 }
 
-class CancelTypeCheckException {
-  final Node node;
-  final String reason;
-
-  CancelTypeCheckException(this.node, this.reason);
-}
-
 /**
  * [ElementAccess] represents the access of [element], either as a property
  * access or invocation.
@@ -134,14 +118,6 @@
     listType = compiler.listClass.computeType(compiler);
   }
 
-  DartType fail(node, [reason]) {
-    String message = 'cannot type-check';
-    if (reason != null) {
-      message = '$message: $reason';
-    }
-    throw new CancelTypeCheckException(node, message);
-  }
-
   reportTypeWarning(Node node, MessageKind kind, [Map arguments = const {}]) {
     compiler.reportWarning(node, new TypeWarning(kind, arguments));
   }
@@ -164,9 +140,9 @@
 
   DartType analyze(Node node) {
     if (node == null) {
-      final String error = 'internal error: unexpected node: null';
+      final String error = 'unexpected node: null';
       if (lastSeenNode != null) {
-        fail(null, error);
+        compiler.internalError(error, node: lastSeenNode);
       } else {
         compiler.cancel(error);
       }
@@ -174,9 +150,8 @@
       lastSeenNode = node;
     }
     DartType result = node.accept(this);
-    // TODO(karlklose): record type?
     if (result == null) {
-      fail(node, 'internal error: type is null');
+      compiler.internalError('type is null', node: node);
     }
     return result;
   }
@@ -212,6 +187,11 @@
 
   DartType visitCascade(Cascade node) {
     analyze(node.expression);
+    if (node.expression.asCascadeReceiver() == null) {
+      // TODO(karlklose): bug: expressions of the form e..x = y do not have
+      // a CascadeReceiver as expression currently.
+      return types.dynamicType;
+    }
     return popCascadeType();
   }
 
@@ -222,15 +202,15 @@
   }
 
   DartType visitClassNode(ClassNode node) {
-    fail(node);
+    compiler.internalError('unexpected node type', node: node);
   }
 
   DartType visitMixinApplication(MixinApplication node) {
-    fail(node);
+    compiler.internalError('unexpected node type', node: node);
   }
 
   DartType visitNamedMixinApplication(NamedMixinApplication node) {
-    fail(node);
+    compiler.internalError('unexpected node type', node: node);
   }
 
   DartType visitDoWhile(DoWhile node) {
@@ -250,7 +230,9 @@
   /** Dart Programming Language Specification: 11.5.1 For Loop */
   DartType visitFor(For node) {
     analyzeWithDefault(node.initializer, StatementType.NOT_RETURNING);
-    checkCondition(node.condition);
+    if (node.condition != null) {
+      checkCondition(node.condition);
+    }
     analyzeWithDefault(node.update, StatementType.NOT_RETURNING);
     StatementType bodyType = analyze(node.body);
     return bodyType.join(StatementType.NOT_RETURNING);
@@ -456,8 +438,9 @@
           checkAssignable(secondArgument, boolType, secondArgumentType);
         }
         return boolType;
+      } else {
+        return unhandledExpression();
       }
-      fail(selector, 'unexpected operator ${name}');
 
     } else if (node.isPropertyAccess) {
       if (node.receiver != null) {
@@ -468,18 +451,18 @@
       return computeType(element);
 
     } else if (node.isFunctionObjectInvocation) {
-      fail(node.receiver, 'function object invocation unimplemented');
+      return unhandledExpression();
     } else {
       ElementAccess computeMethod() {
         if (node.receiver != null) {
           // e.foo() for some expression e.
           DartType receiverType = analyze(node.receiver);
-          if (receiverType.element == compiler.dynamicClass) {
+          if (receiverType.element == compiler.dynamicClass ||
+              receiverType == null ||
+              receiverType.isMalformed ||
+              receiverType.isVoid) {
             return const DynamicAccess();
           }
-          if (receiverType == null) {
-            fail(node.receiver, 'receiverType is null');
-          }
           TypeKind receiverKind = receiverType.kind;
           if (identical(receiverKind, TypeKind.TYPEDEF)) {
             // TODO(karlklose): handle typedefs.
@@ -489,9 +472,13 @@
             // TODO(karlklose): handle type variables.
             return const DynamicAccess();
           }
-          if (!identical(receiverKind, TypeKind.INTERFACE)) {
-            fail(node.receiver, 'unexpected receiver kind: ${receiverKind}');
+          if (identical(receiverKind, TypeKind.FUNCTION)) {
+            // TODO(karlklose): handle getters.
+            return const DynamicAccess();
           }
+          assert(invariant(node.receiver,
+              identical(receiverKind, TypeKind.INTERFACE),
+              message: "interface type expected, got ${receiverKind}"));
           return lookupMethod(selector, receiverType, selector.source);
         } else {
           if (Elements.isUnresolved(element)) {
@@ -503,8 +490,15 @@
           } else if (element.isVariable() || element.isField()) {
             // foo() where foo is a field in the same class.
             return new ResolvedAccess(element);
+          } else if (element.isGetter()) {
+            // TODO(karlklose): handle getters.
+            return const DynamicAccess();
+          } else if (element.isClass()) {
+            // TODO(karlklose): handle type literals.
+            return const DynamicAccess();
           } else {
-            fail(node, 'unexpected element kind ${element.kind}');
+            compiler.internalErrorOnElement(
+                element, 'unexpected element kind ${element.kind}');
           }
         }
       }
@@ -586,7 +580,7 @@
   }
 
   DartType visitOperator(Operator node) {
-    fail(node, 'internal error');
+    compiler.internalError('unexpected node type', node: node);
   }
 
   DartType visitRethrow(Rethrow node) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 24ed91d..0e25098 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -831,12 +831,18 @@
           sideEffects.setChangesInstanceProperty();
         } else if (selector.isGetter()) {
           sideEffects.setDependsOnInstancePropertyStore();
+        } else {
+          sideEffects.setAllSideEffects();
+          sideEffects.setDependsOnSomething();
         }
       } else {
         if (selector.isSetter()) {
           sideEffects.setChangesStaticProperty();
         } else if (selector.isGetter()) {
           sideEffects.setDependsOnStaticPropertyStore();
+        } else {
+          sideEffects.setAllSideEffects();
+          sideEffects.setDependsOnSomething();
         }
       }
     } else if (callee.isGetter() && !selector.isGetter()) {
@@ -860,6 +866,8 @@
                              Selector constraint,
                              SideEffects sideEffects,
                              bool inLoop) {
+    updateSideEffects(sideEffects, selector, callee);
+
     // Bailout for closure calls. We're not tracking types of
     // arguments for closures.
     if (callee.isInstanceMember() && selector.isClosureCall()) {
@@ -878,7 +886,6 @@
       }
     }
 
-    updateSideEffects(sideEffects, selector, callee);
     assert(isNotClosure(caller));
     callee = callee.implementation;
     if (!analyzeCount.containsKey(caller)) {
@@ -1948,16 +1955,6 @@
     }
     Selector selector = elements.getSelector(node);
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
-    if (Elements.isUnresolved(element)
-        || element.isGetter()
-        || element.isField()) {
-      if (element.isGetter()) {
-        handleStaticSend(node, new Selector.getterFrom(selector),
-                         element, null);
-      }
-      return inferrer.dynamicType;
-    }
-
     if (!selector.applies(element, compiler)) return inferrer.dynamicType;
 
     handleStaticSend(node, selector, element, arguments);
@@ -1965,8 +1962,12 @@
       return inferrer.growableListType;
     } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
       return inferrer.fixedListType;
-    } else {
+    } else if (element.isFunction() || element.isConstructor()) {
       return inferrer.returnTypeOfElement(element);
+    } else {
+      assert(element.isField() || element.isGetter());
+      // Closure call.
+      return inferrer.dynamicType;
     }
   }
 
@@ -2026,7 +2027,12 @@
       return inferrer.boolType;
     } else if (const SourceString("as") == op.source) {
       node.visitChildren(this);
-      return inferrer.dynamicType;
+      DartType type = elements.getType(node.arguments.head);
+      if (type.isDynamic) return inferrer.dynamicType;
+      if (type.kind == TypeKind.TYPEDEF) {
+        return inferrer.functionType.nullable();
+      }
+      return new TypeMask.subtype(type);
     } else if (node.isParameterCheck) {
       node.visitChildren(this);
       return inferrer.boolType;
@@ -2074,13 +2080,17 @@
   TypeMask visitClosureSend(Send node) {
     node.visitChildren(this);
     Element element = elements[node];
+    Selector selector = elements.getSelector(node);
     if (element != null && element.isFunction()) {
       assert(Elements.isLocal(element));
       // This only works for function statements. We need a
       // more sophisticated type system with function types to support
       // more.
+      inferrer.updateSideEffects(sideEffects, selector, element);
       return inferrer.returnTypeOfElement(element);
     }
+    sideEffects.setDependsOnSomething();
+    sideEffects.setAllSideEffects();
     return inferrer.dynamicType;
   }
 
diff --git a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
index 1f9d63f..87d3fb3 100644
--- a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
+++ b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
@@ -24,37 +24,24 @@
     print('Request for ${request.uri} ${response.statusCode}');
   }
 
-  setUpErrorHandler() {
-    // TODO(ahe): When https://codereview.chromium.org/13467004/ lands
-    // apply the following changes:
-    // 1. Inline this method in [handle].
-    // 2. Delete this method.
-    // 3. Call response.close() instead of calling [done].
-    // 4. Delete this [done].
-    response.done
-      ..then(onClosed)
-      ..catchError(onError);
-  }
-
-  done() {
-    setUpErrorHandler();
-    response.close();
-  }
-
   notFound(path) {
     response.statusCode = HttpStatus.NOT_FOUND;
     response.write(htmlInfo('Not Found',
                             'The file "$path" could not be found.'));
-    done();
+    response.close();
   }
 
   redirect(String location) {
     response.statusCode = HttpStatus.FOUND;
     response.headers.add(HttpHeaders.LOCATION, location);
-    done();
+    response.close();
   }
 
   handle() {
+    response.done
+      ..then(onClosed)
+      ..catchError(onError);
+
     String path = request.uri.path;
     if (path == '/') return redirect('/$landingPage');
     if (path == '/favicon.ico') {
@@ -72,8 +59,9 @@
         response.headers.set(CONTENT_TYPE, 'application/javascript');
       } else if (path.endsWith('.ico')) {
         response.headers.set(CONTENT_TYPE, 'image/x-icon');
+      } else if (path.endsWith('.appcache')) {
+        response.headers.set(CONTENT_TYPE, 'text/cache-manifest');
       }
-      setUpErrorHandler();
       f.openRead().pipe(response);
     });
   }
@@ -112,7 +100,14 @@
     Conversation.landingPage = arguments[0];
   }
   var host = '127.0.0.1';
-  HttpServer.bind(host, 0).then((HttpServer server) {
+  if (arguments.length > 1) {
+    host = arguments[1];
+  }
+  int port = 0;
+  if (arguments.length > 2) {
+    port = int.parse(arguments[2]);
+  }
+  HttpServer.bind(host, port).then((HttpServer server) {
     print('HTTP server started on http://$host:${server.port}/');
     server.listen(Conversation.onRequest, onError: Conversation.onError);
   }).catchError((e) {
diff --git a/sdk/lib/_internal/pub/bin/pub.dart b/sdk/lib/_internal/pub/bin/pub.dart
index f3b8674..d8e26ed 100644
--- a/sdk/lib/_internal/pub/bin/pub.dart
+++ b/sdk/lib/_internal/pub/bin/pub.dart
@@ -80,6 +80,8 @@
       break;
   }
 
+  log.fine('Pub ${sdk.version}');
+
   var cacheDir;
   if (Platform.environment.containsKey('PUB_CACHE')) {
     cacheDir = Platform.environment['PUB_CACHE'];
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index fb0a842..68bbf32 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -9,6 +9,7 @@
 import 'package:pathos/path.dart' as path;
 
 import 'command_cache.dart';
+import 'command_deploy.dart';
 import 'command_help.dart';
 import 'command_install.dart';
 import 'command_lish.dart';
@@ -29,6 +30,7 @@
   static Map<String, PubCommand> get commands {
     var commands = {
       'cache': new CacheCommand(),
+      'deploy': new DeployCommand(),
       'help': new HelpCommand(),
       'install': new InstallCommand(),
       'publish': new LishCommand(),
diff --git a/sdk/lib/_internal/pub/lib/src/command_deploy.dart b/sdk/lib/_internal/pub/lib/src/command_deploy.dart
new file mode 100644
index 0000000..94decb6
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/command_deploy.dart
@@ -0,0 +1,141 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library command_deploy;
+
+import 'dart:async';
+import 'dart:math' as math;
+
+import 'package:analyzer_experimental/analyzer.dart';
+import 'package:pathos/path.dart' as path;
+
+import 'command.dart';
+import 'dart.dart' as dart;
+import 'io.dart';
+import 'log.dart' as log;
+import 'utils.dart';
+
+final _arrow = getSpecial('\u2192', '=>');
+
+/// Handles the `deploy` pub command.
+class DeployCommand extends PubCommand {
+  final description = "Copy and compile all Dart entrypoints in the 'web' "
+      "directory.";
+  final usage = "pub deploy [options]";
+  final aliases = const ["settle-up"];
+
+  // TODO(nweiz): make these configurable.
+  /// The path to the source directory of the deployment.
+  String get source => path.join(entrypoint.root.dir, 'web');
+
+  /// The path to the target directory of the deployment.
+  String get target => path.join(entrypoint.root.dir, 'deploy');
+
+  /// The set of Dart entrypoints in [source] that should be compiled to [out].
+  final _entrypoints = new List<String>();
+
+  int _maxVerbLength;
+  int _maxSourceLength;
+
+  Future onRun() {
+    if (!dirExists(source)) {
+      throw new ApplicationException("There is no '$source' directory.");
+    }
+
+    return entrypoint.packageFiles(beneath: source).then((files) {
+      log.message("Finding entrypoints...");
+      _findEntrypoints(files);
+      _computeLogSize();
+
+      cleanDir(target);
+      _logAction("Copying", "${path.relative(source)}/",
+          "${path.relative(target)}/");
+      copyFiles(files.where((file) => path.extension(file) != '.dart'),
+          source, target);
+
+      return Future.forEach(_entrypoints, (sourceFile) {
+        var targetFile =
+            path.join(target, path.relative(sourceFile, from: source));
+        var relativeTargetFile = path.relative(targetFile);
+        var relativeSourceFile = path.relative(sourceFile);
+
+        ensureDir(path.dirname(targetFile));
+        _logAction("Compiling", relativeSourceFile, "$relativeTargetFile.js");
+        // TODO(nweiz): print dart2js errors/warnings in red.
+        return dart.compile(sourceFile, packageRoot: entrypoint.packagesDir)
+            .then((js) {
+          writeTextFile("$targetFile.js", js, dontLogContents: true);
+          _logAction("Compiling", relativeSourceFile, "$relativeTargetFile");
+          return dart.compile(sourceFile,
+              packageRoot: entrypoint.packagesDir, toDart: true);
+        }).then((dart) {
+          writeTextFile(targetFile, dart, dontLogContents: true);
+          // TODO(nweiz): we should put dart.js files next to any HTML file
+          // rather than any entrypoint. An HTML file could import an entrypoint
+          // that's not adjacent.
+          _maybeAddDartJs(path.dirname(targetFile));
+        });
+      });
+    });
+  }
+
+  /// Populates [_entrypoints] with all of the Dart entrypoints in [files].
+  /// [files] should be a list of paths in [source].
+  void _findEntrypoints(List<String> files) {
+    for (var file in files) {
+      if (path.extension(file) != '.dart') continue;
+      try {
+        if (!dart.isEntrypoint(parseDartFile(file))) continue;
+      } on AnalyzerErrorGroup catch (e) {
+        log.warning(e.message);
+        continue;
+      }
+      _entrypoints.add(file);
+    }
+    // Sort to ensure a deterministic order of compilation and output.
+    _entrypoints.sort();
+  }
+
+  /// Computes the maximum widths of words that will be used in log output for
+  /// the deploy command so we know how much padding to add when printing them.
+  /// This should only be run after [_findEntrypoints].
+  void _computeLogSize() {
+    _maxVerbLength = ["Copying", "Compiling"]
+        .map((verb) => verb.length).reduce(math.max);
+    var sourceLengths = new List.from(
+            _entrypoints.map((file) => path.relative(file).length))
+        ..add("${path.relative(source)}/".length);
+    if (_shouldAddDartJs) sourceLengths.add("package:browser/dart.js".length);
+    _maxSourceLength = sourceLengths.reduce(math.max);
+  }
+
+  /// Log a deployment action. This should only be run after [_computeLogSize].
+  void _logAction(String verb, String source, String target) {
+    verb = padRight(verb, _maxVerbLength);
+    source = padRight(source, _maxSourceLength);
+    log.message("$verb $source $_arrow $target");
+  }
+
+  // TODO(nweiz): do something more principled when issue 6101 is fixed.
+  /// If this package depends non-transitively on the `browser` package, this
+  /// ensures that the `dart.js` file is copied into [directory], under
+  /// `packages/browser/`.
+  void _maybeAddDartJs(String directory) {
+    var jsPath = path.join(directory, 'packages', 'browser', 'dart.js');
+    // TODO(nweiz): warn if they don't depend on browser?
+    if (!_shouldAddDartJs || fileExists(jsPath)) return;
+
+    _logAction("Copying", "package:browser/dart.js", path.relative(jsPath));
+    ensureDir(path.dirname(jsPath));
+    copyFile(path.join(entrypoint.packagesDir, 'browser', 'dart.js'), jsPath);
+  }
+
+  /// Whether we should copy the browser package's dart.js file into the
+  /// deployed app.
+  bool get _shouldAddDartJs {
+    return !_entrypoints.isEmpty &&
+        entrypoint.root.dependencies.any((dep) =>
+            dep.name == 'browser' && dep.source.name == 'hosted');
+  }
+}
diff --git a/sdk/lib/_internal/pub/lib/src/command_lish.dart b/sdk/lib/_internal/pub/lib/src/command_lish.dart
index 44a13ae..4d97b52 100644
--- a/sdk/lib/_internal/pub/lib/src/command_lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command_lish.dart
@@ -106,14 +106,14 @@
       exit(exit_codes.USAGE);
     }
 
-    var packageBytesFuture = _filesToPublish.then((files) {
+    var packageBytesFuture = entrypoint.packageFiles().then((files) {
       log.fine('Archiving and publishing ${entrypoint.root}.');
 
       // Show the package contents so the user can verify they look OK.
       var package = entrypoint.root;
       log.message(
           'Publishing "${package.name}" ${package.version}:\n'
-          '${generateTree(files)}');
+          '${generateTree(files, baseDir: entrypoint.root.dir)}');
 
       return createTarGz(files, baseDir: entrypoint.root.dir);
     }).then((stream) => stream.toBytes());
@@ -125,39 +125,6 @@
     });
   }
 
-  /// The basenames of files that are automatically excluded from archives.
-  final _BLACKLISTED_FILES = const ['pubspec.lock'];
-
-  /// The basenames of directories that are automatically excluded from
-  /// archives.
-  final _BLACKLISTED_DIRS = const ['packages'];
-
-  /// Returns a list of files that should be included in the published package.
-  /// If this is a Git repository, this will respect .gitignore; otherwise, it
-  /// will return all non-hidden files.
-  Future<List<String>> get _filesToPublish {
-    var rootDir = entrypoint.root.dir;
-
-    return git.isInstalled.then((gitInstalled) {
-      if (dirExists(path.join(rootDir, '.git')) && gitInstalled) {
-        // List all files that aren't gitignored, including those not checked
-        // in to Git.
-        return git.run(["ls-files", "--cached", "--others",
-                        "--exclude-standard"]);
-      }
-
-      return listDir(rootDir, recursive: true)
-          .where(fileExists) // Skip directories and broken symlinks.
-          .map((entry) => path.relative(entry, from: rootDir));
-    }).then((files) => files.where(_shouldPublish).toList());
-  }
-
-  /// Returns `true` if [file] should be published.
-  bool _shouldPublish(String file) {
-    if (_BLACKLISTED_FILES.contains(path.basename(file))) return false;
-    return !path.split(file).any(_BLACKLISTED_DIRS.contains);
-  }
-
   /// Returns the value associated with [key] in [map]. Throws a user-friendly
   /// error if [map] doens't contain [key].
   _expectField(Map map, String key, http.Response response) {
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
new file mode 100644
index 0000000..819053c
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A library for compiling Dart code and manipulating analyzer parse trees.
+library dart;
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:math' as math;
+
+import 'package:analyzer_experimental/analyzer.dart';
+import 'package:pathos/path.dart' as path;
+import '../../../compiler/compiler.dart' as compiler;
+import '../../../compiler/implementation/mirrors/dart2js_mirror.dart' as dart2js
+    show analyze, Dart2JsMirrorSystem;
+import '../../../compiler/implementation/mirrors/mirrors.dart'
+    show MirrorSystem;
+import '../../../compiler/implementation/source_file_provider.dart'
+    show FormattingDiagnosticHandler, SourceFileProvider;
+import '../../../compiler/implementation/filenames.dart'
+    show appendSlash;
+
+import 'io.dart';
+import 'sdk.dart' as sdk;
+import 'utils.dart';
+
+/// Returns [entrypoint] compiled to JavaScript (or to Dart if [toDart] is
+/// true).
+///
+/// By default, the package root is assumed to be adjacent to [entrypoint], but
+/// if [packageRoot] is passed that will be used instead.
+Future<String> compile(String entrypoint, {String packageRoot,
+    bool toDart: false}) {
+  return new Future.sync(() {
+    var provider = new SourceFileProvider();
+    var options = <String>['--categories=Client,Server', '--minify'];
+    if (toDart) options.add('--output-type=dart');
+    if (packageRoot == null) {
+      packageRoot = path.join(path.dirname(entrypoint), 'packages');
+    }
+
+    return compiler.compile(
+        pathToFileUri(entrypoint),
+        pathToFileUri(appendSlash(_libPath)),
+        pathToFileUri(appendSlash(packageRoot)),
+        provider.readStringFromUri,
+        new FormattingDiagnosticHandler(provider).diagnosticHandler,
+        options);
+  }).then((result) {
+    if (result != null) return result;
+    throw new ApplicationException('Failed to compile "$entrypoint".');
+  });
+}
+
+/// Returns the path to the library directory. This corresponds to the "sdk"
+/// directory in the repo and to the root of the compiled SDK.
+String get _libPath {
+  if (runningFromSdk) return sdk.rootDirectory;
+  return path.join(repoRoot, 'sdk');
+}
+
+/// Returns whether [dart] looks like an entrypoint file.
+bool isEntrypoint(CompilationUnit dart) {
+  // TODO(nweiz): this misses the case where a Dart file doesn't contain main(),
+  // but it parts in another file that does.
+  return dart.declarations.any((node) {
+    return node is FunctionDeclaration && node.name.name == "main" &&
+        node.functionExpression.parameters.elements.isEmpty;
+  });
+}
diff --git a/sdk/lib/_internal/pub/lib/src/directory_tree.dart b/sdk/lib/_internal/pub/lib/src/directory_tree.dart
index 25f83f0..a4d501e 100644
--- a/sdk/lib/_internal/pub/lib/src/directory_tree.dart
+++ b/sdk/lib/_internal/pub/lib/src/directory_tree.dart
@@ -56,10 +56,12 @@
 ///         |-- relative_test.dart
 ///         '-- split_test.dart
 ///
-String generateTree(List<String> files) {
+/// If [baseDir] is passed, it will be used as the root of the tree.
+String generateTree(List<String> files, {String baseDir}) {
   // Parse out the files into a tree of nested maps.
   var root = {};
   for (var file in files) {
+    if (baseDir != null) file = path.relative(file, from: baseDir);
     var parts = path.split(file);
     var directory = root;
     for (var part in path.split(file)) {
diff --git a/sdk/lib/_internal/pub/lib/src/entrypoint.dart b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
index 9341c9b..359c77b 100644
--- a/sdk/lib/_internal/pub/lib/src/entrypoint.dart
+++ b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
@@ -8,6 +8,7 @@
 
 import 'package:pathos/path.dart' as path;
 
+import 'git.dart' as git;
 import 'io.dart';
 import 'lock_file.dart';
 import 'log.dart' as log;
@@ -215,4 +216,44 @@
     if (entryExists(symlink)) deleteEntry(symlink);
     createSymlink(packagesDir, symlink, relative: true);
   }
+
+  /// The basenames of files that are automatically excluded from archives.
+  final _BLACKLISTED_FILES = const ['pubspec.lock'];
+
+  /// The basenames of directories that are automatically excluded from
+  /// archives.
+  final _BLACKLISTED_DIRS = const ['packages'];
+
+  // TODO(nweiz): unit test this function.
+  /// Returns a list of files that are considered to be part of this package.
+  ///
+  /// If this is a Git repository, this will respect .gitignore; otherwise, it
+  /// will return all non-hidden, non-blacklisted files.
+  ///
+  /// If [beneath] is passed, this will only return files beneath that path.
+  Future<List<String>> packageFiles({String beneath}) {
+    if (beneath == null) beneath = root.dir;
+
+    return git.isInstalled.then((gitInstalled) {
+      if (dirExists(path.join(root.dir, '.git')) && gitInstalled) {
+        // List all files that aren't gitignored, including those not checked
+        // in to Git.
+        return git.run(["ls-files", "--cached", "--others",
+                        "--exclude-standard", beneath]).then((files) {
+          // Git always prints files relative to the project root, but we want
+          // them relative to the working directory.
+          return files.map((file) => path.join(root.dir, file));
+        });
+      }
+
+      // Skip directories and broken symlinks.
+      return listDir(beneath, recursive: true).where(fileExists);
+    }).then((files) {
+      return files.where((file) {
+        var relative = path.relative(file, from: beneath);
+        if (_BLACKLISTED_FILES.contains(path.basename(relative))) return false;
+        return !path.split(relative).any(_BLACKLISTED_DIRS.contains);
+      }).toList();
+    });
+  }
 }
diff --git a/sdk/lib/_internal/pub/lib/src/http.dart b/sdk/lib/_internal/pub/lib/src/http.dart
index eecfda3..00fa952 100644
--- a/sdk/lib/_internal/pub/lib/src/http.dart
+++ b/sdk/lib/_internal/pub/lib/src/http.dart
@@ -31,6 +31,8 @@
 /// An HTTP client that transforms 40* errors and socket exceptions into more
 /// user-friendly error messages.
 class PubHttpClient extends http.BaseClient {
+  final _requestStopwatches = new Map<http.BaseRequest, Stopwatch>();
+
   http.Client inner;
 
   PubHttpClient([http.Client inner])
@@ -41,6 +43,7 @@
   }
 
   Future<http.StreamedResponse> send(http.BaseRequest request) {
+    _requestStopwatches[request] = new Stopwatch()..start();
     _logRequest(request);
 
     // TODO(nweiz): remove this when issue 4061 is fixed.
@@ -128,8 +131,10 @@
 
     var responseLog = new StringBuffer();
     var request = response.request;
+    var stopwatch = _requestStopwatches.remove(request)..stop();
     responseLog.writeln("HTTP response ${response.statusCode} "
         "${response.reasonPhrase} for ${request.method} ${request.url}");
+    responseLog.writeln("took ${stopwatch.elapsed}");
     response.headers.forEach((name, value) =>
         responseLog.writeln(_logField(name, value)));
 
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index 46e5255..122bcf0 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -185,6 +185,22 @@
   });
 }
 
+/// Copy all files in [files] to the directory [destination]. Their locations in
+/// [destination] will be determined by their relative location to [baseDir].
+/// Any existing files at those paths will be overwritten.
+void copyFiles(Iterable<String> files, String baseDir, String destination) {
+  for (var file in files) {
+    var newPath = path.join(destination, path.relative(file, from: baseDir));
+    ensureDir(path.dirname(newPath));
+    copyFile(file, newPath);
+  }
+}
+
+/// Copy a file from [source] to [destination].
+void copyFile(String source, String destination) {
+  writeBinaryFile(destination, readBinaryFile(source));
+}
+
 /// Creates a directory [dir].
 String createDir(String dir) {
   new Directory(dir).createSync();
@@ -388,7 +404,11 @@
 /// should just be a fragment like, "Are you sure you want to proceed".
 Future<bool> confirm(String message) {
   log.fine('Showing confirm message: $message');
-  stdout.write("$message (y/n)? ");
+  if (runningAsTest) {
+    log.message("$message (y/n)?");
+  } else {
+    stdout.write("$message (y/n)? ");
+  }
   return streamFirst(stdinLines)
       .then((line) => new RegExp(r"^[yY]").hasMatch(line));
 }
diff --git a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
index efb6fba..97d35da 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
@@ -98,6 +98,8 @@
   Future<SolveResult> solve() {
     var stopwatch = new Stopwatch();
 
+    _logParameters();
+
     return new Future(() {
       stopwatch.start();
 
@@ -284,6 +286,23 @@
     return walkDeps(depender, depender.name);
   }
 
+  /// Logs the initial parameters to the solver.
+  void _logParameters() {
+    var buffer = new StringBuffer();
+    buffer.writeln("Solving dependencies:");
+    for (var package in root.dependencies) {
+      buffer.write("- $package");
+      if (_forceLatest.contains(package.name)) {
+        buffer.write(" (use latest)");
+      } else if (lockFile.packages.containsKey(package.name)) {
+        var version = lockFile.packages[package.name].version;
+        buffer.write(" (locked to $version)");
+      }
+      buffer.writeln();
+    }
+    log.solver(buffer.toString().trim());
+  }
+
   /// Logs [message] in the context of the current selected packages. If
   /// [message] is omitted, just logs a description of leaf-most selection.
   void logSolve([String message]) {
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index 80a8ec3..08b0fb4 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -12,6 +12,8 @@
 import 'dart:mirrors';
 import 'dart:uri';
 
+import 'package:pathos/path.dart' as path;
+
 /// A pair of values.
 class Pair<E, F> {
   E first;
@@ -211,6 +213,26 @@
   return new Pair<Stream, Stream>(controller1.stream, controller2.stream);
 }
 
+/// Merges [stream1] and [stream2] into a single stream that emits events from
+/// both sources.
+Stream mergeStreams(Stream stream1, Stream stream2) {
+  var doneCount = 0;
+  var controller = new StreamController();
+
+  for (var stream in [stream1, stream2]) {
+    stream.listen((value) {
+      controller.add(value);
+    }, onError: (error) {
+      controller.addError(error);
+    }, onDone: () {
+      doneCount++;
+      if (doneCount == 2) controller.close();
+    });
+  }
+
+  return controller.stream;
+}
+
 /// A regular expression matching a trailing CR character.
 final _trailingCR = new RegExp(r"\r$");
 
@@ -384,6 +406,32 @@
   }
 }
 
+/// Converts a local path string to a `file:` [Uri].
+Uri pathToFileUri(String pathString) {
+  pathString = path.absolute(pathString);
+  if (Platform.operatingSystem != 'windows') {
+    return Uri.parse('file://$pathString');
+  } else if (path.rootPrefix(pathString).startsWith('\\\\')) {
+    // Network paths become "file://hostname/path/to/file".
+    return Uri.parse('file:${pathString.replaceAll("\\", "/")}');
+  } else {
+    // Drive-letter paths become "file:///C:/path/to/file".
+    return Uri.parse('file:///${pathString.replaceAll("\\", "/")}');
+  }
+}
+
+/// Gets a "special" string (ANSI escape or Unicode). On Windows, returns
+/// something else since those aren't supported.
+String getSpecial(String color, [String onWindows = '']) {
+  // No ANSI escapes on windows or when running tests.
+  if (runningAsTest || Platform.operatingSystem == 'windows') return onWindows;
+  return color;
+}
+
+/// Whether pub is running as a subprocess in an integration test.
+bool get runningAsTest =>
+  Platform.environment.containsKey('_PUB_TESTING');
+
 /// Wraps [fn] to guard against several different kinds of stack overflow
 /// exceptions:
 ///
@@ -416,6 +464,8 @@
   final String message;
 
   ApplicationException(this.message);
+
+  String toString() => message;
 }
 
 /// Throw a [ApplicationException] with [message].
diff --git a/sdk/lib/_internal/pub/test/command_line_config.dart b/sdk/lib/_internal/pub/test/command_line_config.dart
index 8a929e4..ed55aff 100644
--- a/sdk/lib/_internal/pub/test/command_line_config.dart
+++ b/sdk/lib/_internal/pub/test/command_line_config.dart
@@ -11,23 +11,15 @@
 import 'package:unittest/unittest.dart';
 import '../lib/src/utils.dart';
 
-/// Gets a "special" string (ANSI escape or Unicode). On Windows, returns
-/// something else since those aren't supported.
-String _getSpecial(String color, [String onWindows = '']) {
-  // No ANSI escapes on windows.
-  if (Platform.operatingSystem == 'windows') return onWindows;
-  return color;
-}
-
 /// Pretty Unicode characters!
-final _checkbox = _getSpecial('\u2713', 'PASS');
-final _ballotX  = _getSpecial('\u2717', 'FAIL');
-final _lambda   = _getSpecial('\u03bb', '<fn>');
+final _checkbox = getSpecial('\u2713', 'PASS');
+final _ballotX  = getSpecial('\u2717', 'FAIL');
+final _lambda   = getSpecial('\u03bb', '<fn>');
 
-final _green = _getSpecial('\u001b[32m');
-final _red = _getSpecial('\u001b[31m');
-final _magenta = _getSpecial('\u001b[35m');
-final _none = _getSpecial('\u001b[0m');
+final _green = getSpecial('\u001b[32m');
+final _red = getSpecial('\u001b[31m');
+final _magenta = getSpecial('\u001b[35m');
+final _none = getSpecial('\u001b[0m');
 
 /// A custom unittest configuration for running the pub tests from the
 /// command-line and generating human-friendly output.
diff --git a/sdk/lib/_internal/pub/test/deploy/compiles_dart_entrypoints_to_dart_and_js.dart b/sdk/lib/_internal/pub/test/deploy/compiles_dart_entrypoints_to_dart_and_js.dart
new file mode 100644
index 0000000..46a9593
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/deploy/compiles_dart_entrypoints_to_dart_and_js.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("compiles Dart entrypoints to Dart and JS", () {
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.dir('web', [
+        d.file('file.dart', 'void main() => print("hello");'),
+        d.dir('subdir', [
+          d.file('subfile.dart', 'void main() => print("ping");')
+        ])
+      ])
+    ]).create();
+
+    schedulePub(args: ["deploy"],
+        output: '''
+Finding entrypoints...
+Copying   web/                    => deploy/
+Compiling web/file.dart           => deploy/file.dart.js
+Compiling web/file.dart           => deploy/file.dart
+Compiling web/subdir/subfile.dart => deploy/subdir/subfile.dart.js
+Compiling web/subdir/subfile.dart => deploy/subdir/subfile.dart
+''',
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir('deploy', [
+        d.matcherFile('file.dart.js', isNot(isEmpty)),
+        d.matcherFile('file.dart', isNot(isEmpty)),
+        d.dir('subdir', [
+          d.matcherFile('subfile.dart.js', isNot(isEmpty)),
+          d.matcherFile('subfile.dart', isNot(isEmpty))
+        ])
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/deploy/copies_dart_js_next_to_entrypoints.dart b/sdk/lib/_internal/pub/test/deploy/copies_dart_js_next_to_entrypoints.dart
new file mode 100644
index 0000000..8d9248e
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/deploy/copies_dart_js_next_to_entrypoints.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:json' as json;
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("compiles dart.js next to entrypoints", () {
+    serve([
+      d.dir('packages', [
+        d.file('browser.json', json.stringify({'versions': ['1.0.0']})),
+        d.dir('browser', [
+          d.dir('versions', [
+            d.file('1.0.0.yaml', yaml(packageMap("browser", "1.0.0"))),
+            d.tar('1.0.0.tar.gz', [
+              d.file('pubspec.yaml', yaml(packageMap("browser", "1.0.0"))),
+              d.dir('lib', [
+                d.file('dart.js', 'contents of dart.js')
+              ])
+            ])
+          ])
+        ])
+      ])
+    ]);
+
+    d.dir(appPath, [
+      d.appPubspec([dependencyMap("browser", "1.0.0")]),
+      d.dir('web', [
+        d.file('file.dart', 'void main() => print("hello");'),
+        d.dir('subdir', [
+          d.file('subfile.dart', 'void main() => print("subhello");')
+        ])
+      ])
+    ]).create();
+
+    schedulePub(args: ["install"],
+        output: new RegExp(r"Dependencies installed!$"));
+
+    schedulePub(args: ["deploy"],
+        output: '''
+Finding entrypoints...
+Copying   web/                    => deploy/
+Compiling web/file.dart           => deploy/file.dart.js
+Compiling web/file.dart           => deploy/file.dart
+Copying   package:browser/dart.js => deploy/packages/browser/dart.js
+Compiling web/subdir/subfile.dart => deploy/subdir/subfile.dart.js
+Compiling web/subdir/subfile.dart => deploy/subdir/subfile.dart
+Copying   package:browser/dart.js => deploy/subdir/packages/browser/dart.js
+''',
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir('deploy', [
+        d.matcherFile('file.dart.js', isNot(isEmpty)),
+        d.matcherFile('file.dart', isNot(isEmpty)),
+        d.dir('packages', [d.dir('browser', [
+          d.file('dart.js', 'contents of dart.js')
+        ])]),
+        d.dir('subdir', [
+          d.dir('packages', [d.dir('browser', [
+            d.file('dart.js', 'contents of dart.js')
+          ])]),
+          d.matcherFile('subfile.dart.js', isNot(isEmpty)),
+          d.matcherFile('subfile.dart', isNot(isEmpty))
+        ])
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/deploy/copies_non_dart_files_to_deploy.dart b/sdk/lib/_internal/pub/test/deploy/copies_non_dart_files_to_deploy.dart
new file mode 100644
index 0000000..2602b2b
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/deploy/copies_non_dart_files_to_deploy.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("copies non-Dart files to deploy/", () {
+    servePackages([packageMap("browser", "1.0.0")]);
+
+    d.dir(appPath, [
+      // A browser dependency with no entrypoints shouldn't cause dart.js to be
+      // copied in.
+      d.appPubspec([dependencyMap("browser", "1.0.0")]),
+      d.dir('web', [
+        d.file('file.txt', 'contents'),
+        d.dir('subdir', [
+          d.file('subfile.txt', 'subcontents')
+        ])
+      ])
+    ]).create();
+
+    schedulePub(args: ["deploy"],
+        output: '''
+Finding entrypoints...
+Copying   web/ => deploy/
+''',
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir('deploy', [
+        d.nothing('packages'),
+        d.file('file.txt', 'contents'),
+        d.dir('subdir', [
+          d.file('subfile.txt', 'subcontents')
+        ])
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/deploy/ignores_non_entrypoint_dart_files.dart b/sdk/lib/_internal/pub/test/deploy/ignores_non_entrypoint_dart_files.dart
new file mode 100644
index 0000000..249d561
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/deploy/ignores_non_entrypoint_dart_files.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("ignores non-entrypoint Dart files", () {
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.dir('web', [
+        d.file('file1.dart', 'var main = () => print("hello");'),
+        d.file('file2.dart', 'void main(arg) => print("hello");'),
+        d.file('file3.dart', 'class Foo { void main() => print("hello"); }'),
+        d.file('file4.dart', 'var foo;')
+      ])
+    ]).create();
+
+    schedulePub(args: ["deploy"],
+        output: '''
+Finding entrypoints...
+Copying   web/ => deploy/
+''',
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir('deploy', [
+        d.nothing('file1.dart.js'),
+        d.nothing('file1.dart'),
+        d.nothing('file2.dart.js'),
+        d.nothing('file2.dart'),
+        d.nothing('file3.dart.js'),
+        d.nothing('file3.dart')
+        d.nothing('file4.dart.js'),
+        d.nothing('file4.dart')
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/deploy/reports_dart_parse_errors.dart b/sdk/lib/_internal/pub/test/deploy/reports_dart_parse_errors.dart
new file mode 100644
index 0000000..6875a43e
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/deploy/reports_dart_parse_errors.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("reports Dart parse errors", () {
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.dir('web', [
+        d.file('file.txt', 'contents'),
+        d.file('file.dart', 'void void;'),
+        d.dir('subdir', [
+          d.file('subfile.dart', 'void void;')
+        ])
+      ])
+    ]).create();
+
+    schedulePub(args: ["deploy"],
+        error: new RegExp(
+            r"^Error on line 1 of .*[/\\]file\.dart:(.|\n)*"
+            r"^Error on line 1 of .*[/\\]subfile\.dart:",
+            multiLine: true),
+        output: '''
+Finding entrypoints...
+Copying   web/ => deploy/
+''',
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir('deploy', [
+        d.matcherFile('file.txt', 'contents'),
+        d.nothing('file.dart.js'),
+        d.nothing('file.dart'),
+        d.nothing('subdir')
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/deploy/with_no_web_directory.dart b/sdk/lib/_internal/pub/test/deploy/with_no_web_directory.dart
new file mode 100644
index 0000000..0e0044b
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/deploy/with_no_web_directory.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("with no web directory", () {
+    d.appDir([]).create();
+
+    schedulePub(args: ["deploy"],
+        error: new RegExp(r"^There is no '[^']+[/\\]web' directory.$",
+            multiLine: true),
+        exitCode: 1);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart b/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart
index b699d2f4..4e65965 100644
--- a/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart
+++ b/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart
@@ -31,12 +31,8 @@
       request.response.close();
     });
 
-    // TODO(rnystrom): The confirm line is run together with this one because
-    // in normal usage, the user will have entered a newline on stdin which
-    // gets echoed to the terminal. Do something better here?
-    expect(pub.nextLine(), completion(equals(
-        'Looks great! Are you ready to upload your package (y/n)?'
-        ' Package test_pkg 1.0.0 uploaded!')));
+    expect(pub.nextLine(),
+        completion(equals('Package test_pkg 1.0.0 uploaded!')));
     pub.shouldExit(0);
   });
 
diff --git a/sdk/lib/_internal/pub/test/oauth2/utils.dart b/sdk/lib/_internal/pub/test/oauth2/utils.dart
index 5fa2dd6..fa3ce98 100644
--- a/sdk/lib/_internal/pub/test/oauth2/utils.dart
+++ b/sdk/lib/_internal/pub/test/oauth2/utils.dart
@@ -19,12 +19,8 @@
 
 void authorizePub(ScheduledProcess pub, ScheduledServer server,
     [String accessToken="access token"]) {
-  // TODO(rnystrom): The confirm line is run together with this one because
-  // in normal usage, the user will have entered a newline on stdin which
-  // gets echoed to the terminal. Do something better here?
-  expect(pub.nextLine(), completion(equals(
-      'Looks great! Are you ready to upload your package (y/n)? '
-      'Pub needs your authorization to upload packages on your behalf.')));
+  expect(pub.nextLine(), completion(equals('Pub needs your authorization to '
+      'upload packages on your behalf.')));
 
   expect(pub.nextLine().then((line) {
     var match = new RegExp(r'[?&]redirect_uri=([0-9a-zA-Z%+-]+)[$&]')
diff --git a/sdk/lib/_internal/pub/test/pub_test.dart b/sdk/lib/_internal/pub/test/pub_test.dart
index 66eba69..ba97da5 100644
--- a/sdk/lib/_internal/pub/test/pub_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_test.dart
@@ -31,6 +31,7 @@
 
     Available commands:
       cache      Inspect the system cache.
+      deploy     Copy and compile all Dart entrypoints in the 'web' directory.
       help       Display help information for Pub.
       install    Install the current package's dependencies.
       publish    Publish the current package to pub.dartlang.org.
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index e2a06f5..8d417ed 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -33,6 +33,7 @@
 import '../lib/src/hosted_source.dart';
 import '../lib/src/http.dart';
 import '../lib/src/io.dart';
+import '../lib/src/log.dart' as log;
 import '../lib/src/path_source.dart';
 import '../lib/src/safe_http_server.dart';
 import '../lib/src/system_cache.dart';
@@ -99,6 +100,7 @@
       return SafeHttpServer.bind("localhost", 0).then((server) {
         _server = server;
         server.listen((request) {
+          currentSchedule.heartbeat();
           var response = request.response;
           try {
             var path = request.uri.path.replaceFirst("/", "");
@@ -110,6 +112,7 @@
             var stream = baseDir.load(path);
 
             new ByteStream(stream).toBytes().then((data) {
+              currentSchedule.heartbeat();
               response.statusCode = 200;
               response.contentLength = data.length;
               response.add(data);
@@ -333,6 +336,8 @@
   expect(pub.nextLine(), completion(equals("|   '-- test_pkg.dart")));
   expect(pub.nextLine(), completion(equals("'-- pubspec.yaml")));
   expect(pub.nextLine(), completion(equals("")));
+  expect(pub.nextLine(), completion(equals('Looks great! Are you ready to '
+      'upload your package (y/n)?')));
 
   pub.writeLine("y");
 }
@@ -362,7 +367,7 @@
   var pubPath = path.join(testDirectory, '..', 'bin', 'pub.dart');
 
   var dartArgs = ['--package-root=$_packageRoot/', '--checked', pubPath,
-      '--trace'];
+      '--verbose'];
   dartArgs.addAll(args);
 
   if (tokenEndpoint == null) tokenEndpoint = new Future.value();
@@ -371,6 +376,7 @@
     options.workingDirectory = pathInSandbox(appPath);
     // TODO(nweiz): remove this when issue 9294 is fixed.
     options.environment = new Map.from(Platform.environment);
+    options.environment['_PUB_TESTING'] = 'true';
     options.environment['PUB_CACHE'] = pathInSandbox(cachePath);
     options.environment['DART_SDK'] = pathInSandbox(sdkPath);
     if (tokenEndpoint != null) {
@@ -380,10 +386,89 @@
     return options;
   });
 
-  return new ScheduledProcess.start(dartBin, dartArgs, options: optionsFuture,
+  return new PubProcess.start(dartBin, dartArgs, options: optionsFuture,
       description: args.isEmpty ? 'pub' : 'pub ${args.first}');
 }
 
+/// A subclass of [ScheduledProcess] that parses pub's verbose logging output
+/// and makes [nextLine], [nextErrLine], [remainingStdout], and
+/// [remainingStderr] work as though pub weren't running in verbose mode.
+class PubProcess extends ScheduledProcess {
+  Stream<Pair<log.Level, String>> _log;
+  Stream<String> _stdout;
+  Stream<String> _stderr;
+
+  PubProcess.start(executable, arguments,
+      {options, String description, Encoding encoding: Encoding.UTF_8})
+    : super.start(executable, arguments,
+        options: options,
+        description: description,
+        encoding: encoding);
+
+  Stream<Pair<log.Level, String>> _logStream() {
+    if (_log == null) {
+      _log = mergeStreams(
+        _outputToLog(super.stdoutStream(), log.Level.MESSAGE),
+        _outputToLog(super.stderrStream(), log.Level.ERROR));
+    }
+
+    var pair = tee(_log);
+    _log = pair.first;
+    return pair.last;
+  }
+
+  final _logLineRegExp = new RegExp(r"^([A-Z ]{4})[:|] (.*)$");
+  final _logLevels = [
+    log.Level.ERROR, log.Level.WARNING, log.Level.MESSAGE, log.Level.IO,
+    log.Level.SOLVER, log.Level.FINE
+  ].fold(<String, log.Level>{}, (levels, level) {
+    levels[level.name] = level;
+    return levels;
+  });
+
+  Stream<Pair<log.Level, String>> _outputToLog(Stream<String> stream,
+      log.Level defaultLevel) {
+    var lastLevel;
+    return stream.map((line) {
+      var match = _logLineRegExp.firstMatch(line);
+      if (match == null) return new Pair<log.Level, String>(defaultLevel, line);
+
+      var level = _logLevels[match[1]];
+      if (level == null) level = lastLevel;
+      lastLevel = level;
+      return new Pair<log.Level, String>(level, match[2]);
+    });
+  }
+
+  Stream<String> stdoutStream() {
+    if (_stdout == null) {
+      _stdout = _logStream().expand((entry) {
+        if (entry.first != log.Level.MESSAGE) return [];
+        return [entry.last];
+      });
+    }
+
+    var pair = tee(_stdout);
+    _stdout = pair.first;
+    return pair.last;
+  }
+
+  Stream<String> stderrStream() {
+    if (_stderr == null) {
+      _stderr = _logStream().expand((entry) {
+        if (entry.first != log.Level.ERROR && entry.first != log.Level.WARNING) {
+          return [];
+        }
+        return [entry.last];
+      });
+    }
+
+    var pair = tee(_stderr);
+    _stderr = pair.first;
+    return pair.last;
+  }
+}
+
 // TODO(nweiz): use the built-in mechanism for accessing this once it exists
 // (issue 9119).
 /// The path to the `packages` directory from which pub loads its dependencies.
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index b4f7f18..3086f7d 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -167,74 +167,18 @@
   }
 
   Future then(f(T value), { onError(error) }) {
-    if (!_isComplete) {
-      if (onError == null) {
-        return new _ThenFuture(f).._subscribeTo(this);
-      }
-      return new _SubscribeFuture(f, onError).._subscribeTo(this);
+    if (onError == null) {
+      return new _ThenFuture(f).._subscribeTo(this);
     }
-    if (_hasError) {
-      if (onError != null) {
-        return _handleError(onError, null);
-      }
-      // The "f" funtion will never be called, so just return
-      // a future that delegates to this. We don't want to return
-      // this itself to give a signal that the future is complete.
-      return new _FutureWrapper(this);
-    } else {
-      assert(_hasValue);
-      return _handleValue(f);
-    }
+    return new _SubscribeFuture(f, onError).._subscribeTo(this);
   }
 
   Future catchError(f(error), { bool test(error) }) {
-    if (_hasValue) {
-      return new _FutureWrapper(this);
-    }
-    if (!_isComplete) {
-      return new _CatchErrorFuture(f, test).._subscribeTo(this);
-    } else {
-      return _handleError(f, test);
-    }
+    return new _CatchErrorFuture(f, test).._subscribeTo(this);
   }
 
   Future<T> whenComplete(action()) {
-    _WhenFuture<T> whenFuture = new _WhenFuture<T>(action);
-    if (!_isComplete) {
-      _addListener(whenFuture);
-    } else if (_hasValue) {
-      T value = _resultOrListeners;
-      Timer.run(() {
-        whenFuture._sendValue(value);
-      });
-    } else {
-      assert(_hasError);
-      _clearUnhandledError();
-      var error = _resultOrListeners;
-      Timer.run(() {
-        whenFuture._sendError(error);
-      });
-    }
-    return whenFuture;
-  }
-
-  /** Handle a late listener on a completed future with a value. */
-  Future _handleValue(onValue(var value)) {
-    assert(_hasValue);
-    _ThenFuture thenFuture = new _ThenFuture(onValue);
-    T value = _resultOrListeners;
-    Timer.run(() { thenFuture._sendValue(value); });
-    return thenFuture;
-  }
-
-  /** Handle a late listener on a completed future with an error. */
-  Future _handleError(onError(error), bool test(error)) {
-    assert(_hasError);
-    _clearUnhandledError();
-    var error = _resultOrListeners;
-    _CatchErrorFuture errorFuture = new _CatchErrorFuture(onError, test);
-    Timer.run(() { errorFuture._sendError(error); });
-    return errorFuture;
+    return new _WhenFuture<T>(action).._subscribeTo(this);
   }
 
   Stream<T> asStream() => new Stream.fromFuture(this);
@@ -273,7 +217,7 @@
     _state |= _UNHANDLED_ERROR;
     // Wait for the rest of the current event's duration to see
     // if a subscriber is added to handle the error.
-    Timer.run(() {
+    runAsync(() {
       if (_hasUnhandledError) {
         // No error handler has been added since the error was set.
         _clearUnhandledError();
@@ -289,10 +233,24 @@
   }
 
   void _addListener(_FutureListener listener) {
-    assert(!_isComplete);
-    assert(listener._nextListener == null);
-    listener._nextListener = _resultOrListeners;
-    _resultOrListeners = listener;
+    if (_isComplete) {
+      _clearUnhandledError();
+      // Handle late listeners asynchronously.
+      runAsync(() {
+        if (_hasValue) {
+          T value = _resultOrListeners;
+          listener._sendValue(value);
+        } else {
+          assert(_hasError);
+          listener._sendError(_resultOrListeners);
+        }
+      });
+    } else {
+      assert(!_isComplete);
+      assert(listener._nextListener == null);
+      listener._nextListener = _resultOrListeners;
+      _resultOrListeners = listener;
+    }
   }
 
   _FutureListener _removeListeners() {
@@ -513,30 +471,3 @@
     _setError(error);
   }
 }
-
-/**
- * Thin wrapper around a [Future].
- *
- * This is used to return a "new" [Future] that effectively work just
- * as an existing [Future], without making this discoverable by comparing
- * identities.
- */
-class _FutureWrapper<T> implements Future<T> {
-  final Future<T> _future;
-
-  _FutureWrapper(this._future);
-
-  Future then(function(T value), { onError(error) }) {
-    return _future.then(function, onError: onError);
-  }
-
-  Future catchError(function(error), {bool test(var error)}) {
-    return _future.catchError(function, test: test);
-  }
-
-  Future<T> whenComplete(action()) {
-    return _future.whenComplete(action);
-  }
-
-  Stream<T> asStream() => new Stream.fromFuture(_future);
-}
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index cf0bbde..1279426 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -16,6 +16,7 @@
 import 'dart:web_gl' as gl;
 import 'dart:web_sql';
 import 'dart:_js_helper' show convertDartClosureToJS, Creates, JavaScriptIndexingBehavior, JSName, Null, Returns;
+import 'dart:_interceptors' show Interceptor;
 import 'dart:_isolate_helper' show IsolateNatives;
 import 'dart:_foreign_helper' show JS;
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -250,16 +251,28 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => JS('bool', '!!(window.applicationCache)');
 
+  @DomName('DOMApplicationCache.CHECKING')
+  @DocsEditable
   static const int CHECKING = 2;
 
+  @DomName('DOMApplicationCache.DOWNLOADING')
+  @DocsEditable
   static const int DOWNLOADING = 3;
 
+  @DomName('DOMApplicationCache.IDLE')
+  @DocsEditable
   static const int IDLE = 1;
 
+  @DomName('DOMApplicationCache.OBSOLETE')
+  @DocsEditable
   static const int OBSOLETE = 5;
 
+  @DomName('DOMApplicationCache.UNCACHED')
+  @DocsEditable
   static const int UNCACHED = 0;
 
+  @DomName('DOMApplicationCache.UPDATEREADY')
+  @DocsEditable
   static const int UPDATEREADY = 4;
 
   @DomName('DOMApplicationCache.status')
@@ -2041,28 +2054,52 @@
 @DomName('CSSRule')
 class CssRule native "CSSRule" {
 
+  @DomName('CSSRule.CHARSET_RULE')
+  @DocsEditable
   static const int CHARSET_RULE = 2;
 
+  @DomName('CSSRule.FONT_FACE_RULE')
+  @DocsEditable
   static const int FONT_FACE_RULE = 5;
 
+  @DomName('CSSRule.HOST_RULE')
+  @DocsEditable
   static const int HOST_RULE = 1001;
 
+  @DomName('CSSRule.IMPORT_RULE')
+  @DocsEditable
   static const int IMPORT_RULE = 3;
 
+  @DomName('CSSRule.MEDIA_RULE')
+  @DocsEditable
   static const int MEDIA_RULE = 4;
 
+  @DomName('CSSRule.PAGE_RULE')
+  @DocsEditable
   static const int PAGE_RULE = 6;
 
+  @DomName('CSSRule.STYLE_RULE')
+  @DocsEditable
   static const int STYLE_RULE = 1;
 
+  @DomName('CSSRule.UNKNOWN_RULE')
+  @DocsEditable
   static const int UNKNOWN_RULE = 0;
 
+  @DomName('CSSRule.WEBKIT_FILTER_RULE')
+  @DocsEditable
   static const int WEBKIT_FILTER_RULE = 17;
 
+  @DomName('CSSRule.WEBKIT_KEYFRAMES_RULE')
+  @DocsEditable
   static const int WEBKIT_KEYFRAMES_RULE = 7;
 
+  @DomName('CSSRule.WEBKIT_KEYFRAME_RULE')
+  @DocsEditable
   static const int WEBKIT_KEYFRAME_RULE = 8;
 
+  @DomName('CSSRule.WEBKIT_REGION_RULE')
+  @DocsEditable
   static const int WEBKIT_REGION_RULE = 16;
 
   @DomName('CSSRule.cssText')
@@ -2136,9 +2173,13 @@
     return propValue != null ? propValue : '';
   }
 
+  @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
     // try/catch for IE9 which throws on unsupported values.
     try {
+      if (priority == null) {
+        priority = '';
+      }
       JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
       // Bug #2772, IE9 requires a poke to actually apply the value.
       if (JS('bool', '!!#.setAttribute', this)) {
@@ -6824,14 +6865,18 @@
 
 @DocsEditable
 @DomName('DOMStringList')
-class DomStringList extends Object with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List<String> native "DOMStringList" {
+class DomStringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List<String> native "DOMStringList" {
 
   @DomName('DOMStringList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  String operator[](int index) => JS("String", "#[#]", this, index);
-
+  String operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("String", "#[#]", this, index);
+  }
   void operator[]=(int index, String value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -6843,6 +6888,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  String get first {
+    if (this.length > 0) {
+      return JS('String', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  String get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('String', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  String get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('String', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  String elementAt(int index) => this[index];
   // -- end List<String> mixins.
 
   @DomName('DOMStringList.contains')
@@ -7316,18 +7386,29 @@
   void onCreated() {}
 
   // Hooks to support custom WebComponents.
+
+  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
+  Element _xtag;
+
   /**
    * Experimental support for [web components][wc]. This field stores a
    * reference to the component implementation. It was inspired by Mozilla's
    * [x-tags][] project. Please note: in the future it may be possible to
    * `extend Element` from your class, in which case this field will be
-   * deprecated and will simply return this [Element] object.
+   * deprecated.
+   *
+   * If xtag has not been set, it will simply return `this` [Element].
    *
    * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html
    * [x-tags]: http://x-tags.org/
    */
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  var xtag;
+  // Note: return type is `dynamic` for convenience to suppress warnings when
+  // members of the component are used. The actual type is a subtype of Element.
+  get xtag => _xtag != null ? _xtag : this;
+
+  void set xtag(Element value) {
+    _xtag = value;
+  }
 
   /**
    * Scrolls this element into view.
@@ -7551,24 +7632,24 @@
       self._attributeBindings = new Map<String, StreamSubscription>();
     }
 
-    self.attributes.remove(name);
+    self.xtag.attributes.remove(name);
 
     var changed;
     if (name.endsWith('?')) {
       name = name.substring(0, name.length - 1);
 
       changed = (value) {
-        if (_templateBooleanConversion(value)) {
-          self.attributes[name] = '';
+        if (_Bindings._toBoolean(value)) {
+          self.xtag.attributes[name] = '';
         } else {
-          self.attributes.remove(name);
+          self.xtag.attributes.remove(name);
         }
       };
     } else {
       changed = (value) {
         // TODO(jmesserly): escape value if needed to protect against XSS.
-        // See https://github.com/toolkitchen/mdv/issues/58
-        self.attributes[name] = value == null ? '' : '$value';
+        // See https://github.com/polymer-project/mdv/issues/58
+        self.xtag.attributes[name] = value == null ? '' : '$value';
       };
     }
 
@@ -7691,8 +7772,8 @@
     var template = ref;
     if (template == null) template = this;
 
-    var instance = _createDeepCloneAndDecorateTemplates(template.content,
-        attributes['syntax']);
+    var instance = _Bindings._createDeepCloneAndDecorateTemplates(
+        template.content, attributes['syntax']);
 
     if (TemplateElement._instanceCreated != null) {
       TemplateElement._instanceCreated.add(instance);
@@ -7718,7 +7799,7 @@
 
     var syntax = TemplateElement.syntax[attributes['syntax']];
     _model = value;
-    _addBindings(this, model, syntax);
+    _Bindings._addBindings(this, model, syntax);
   }
 
   // TODO(jmesserly): const set would be better
@@ -8022,6 +8103,8 @@
   @DocsEditable
   void click() native;
 
+  @DomName('Element.ALLOW_KEYBOARD_INPUT')
+  @DocsEditable
   static const int ALLOW_KEYBOARD_INPUT = 1;
 
   @JSName('attributes')
@@ -8899,44 +8982,84 @@
     return e;
   }
 
+  @DomName('Event.AT_TARGET')
+  @DocsEditable
   static const int AT_TARGET = 2;
 
+  @DomName('Event.BLUR')
+  @DocsEditable
   static const int BLUR = 8192;
 
+  @DomName('Event.BUBBLING_PHASE')
+  @DocsEditable
   static const int BUBBLING_PHASE = 3;
 
+  @DomName('Event.CAPTURING_PHASE')
+  @DocsEditable
   static const int CAPTURING_PHASE = 1;
 
+  @DomName('Event.CHANGE')
+  @DocsEditable
   static const int CHANGE = 32768;
 
+  @DomName('Event.CLICK')
+  @DocsEditable
   static const int CLICK = 64;
 
+  @DomName('Event.DBLCLICK')
+  @DocsEditable
   static const int DBLCLICK = 128;
 
+  @DomName('Event.DRAGDROP')
+  @DocsEditable
   static const int DRAGDROP = 2048;
 
+  @DomName('Event.FOCUS')
+  @DocsEditable
   static const int FOCUS = 4096;
 
+  @DomName('Event.KEYDOWN')
+  @DocsEditable
   static const int KEYDOWN = 256;
 
+  @DomName('Event.KEYPRESS')
+  @DocsEditable
   static const int KEYPRESS = 1024;
 
+  @DomName('Event.KEYUP')
+  @DocsEditable
   static const int KEYUP = 512;
 
+  @DomName('Event.MOUSEDOWN')
+  @DocsEditable
   static const int MOUSEDOWN = 1;
 
+  @DomName('Event.MOUSEDRAG')
+  @DocsEditable
   static const int MOUSEDRAG = 32;
 
+  @DomName('Event.MOUSEMOVE')
+  @DocsEditable
   static const int MOUSEMOVE = 16;
 
+  @DomName('Event.MOUSEOUT')
+  @DocsEditable
   static const int MOUSEOUT = 8;
 
+  @DomName('Event.MOUSEOVER')
+  @DocsEditable
   static const int MOUSEOVER = 4;
 
+  @DomName('Event.MOUSEUP')
+  @DocsEditable
   static const int MOUSEUP = 2;
 
+  @DomName('Event.NONE')
+  @DocsEditable
   static const int NONE = 0;
 
+  @DomName('Event.SELECT')
+  @DocsEditable
   static const int SELECT = 16384;
 
   @DomName('Event.bubbles')
@@ -9017,8 +9140,12 @@
 @DomName('EventException')
 class EventException native "EventException" {
 
+  @DomName('EventException.DISPATCH_REQUEST_ERR')
+  @DocsEditable
   static const int DISPATCH_REQUEST_ERR = 1;
 
+  @DomName('EventException.UNSPECIFIED_EVENT_TYPE_ERR')
+  @DocsEditable
   static const int UNSPECIFIED_EVENT_TYPE_ERR = 0;
 
   @DomName('EventException.code')
@@ -9074,10 +9201,16 @@
   static EventSource _create_1(url, eventSourceInit) => JS('EventSource', 'new EventSource(#,#)', url, eventSourceInit);
   static EventSource _create_2(url) => JS('EventSource', 'new EventSource(#)', url);
 
+  @DomName('EventSource.CLOSED')
+  @DocsEditable
   static const int CLOSED = 2;
 
+  @DomName('EventSource.CONNECTING')
+  @DocsEditable
   static const int CONNECTING = 0;
 
+  @DomName('EventSource.OPEN')
+  @DocsEditable
   static const int OPEN = 1;
 
   @DomName('EventSource.readyState')
@@ -9344,28 +9477,52 @@
 @DomName('FileError')
 class FileError native "FileError" {
 
+  @DomName('FileError.ABORT_ERR')
+  @DocsEditable
   static const int ABORT_ERR = 3;
 
+  @DomName('FileError.ENCODING_ERR')
+  @DocsEditable
   static const int ENCODING_ERR = 5;
 
+  @DomName('FileError.INVALID_MODIFICATION_ERR')
+  @DocsEditable
   static const int INVALID_MODIFICATION_ERR = 9;
 
+  @DomName('FileError.INVALID_STATE_ERR')
+  @DocsEditable
   static const int INVALID_STATE_ERR = 7;
 
+  @DomName('FileError.NOT_FOUND_ERR')
+  @DocsEditable
   static const int NOT_FOUND_ERR = 1;
 
+  @DomName('FileError.NOT_READABLE_ERR')
+  @DocsEditable
   static const int NOT_READABLE_ERR = 4;
 
+  @DomName('FileError.NO_MODIFICATION_ALLOWED_ERR')
+  @DocsEditable
   static const int NO_MODIFICATION_ALLOWED_ERR = 6;
 
+  @DomName('FileError.PATH_EXISTS_ERR')
+  @DocsEditable
   static const int PATH_EXISTS_ERR = 12;
 
+  @DomName('FileError.QUOTA_EXCEEDED_ERR')
+  @DocsEditable
   static const int QUOTA_EXCEEDED_ERR = 10;
 
+  @DomName('FileError.SECURITY_ERR')
+  @DocsEditable
   static const int SECURITY_ERR = 2;
 
+  @DomName('FileError.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 8;
 
+  @DomName('FileError.TYPE_MISMATCH_ERR')
+  @DocsEditable
   static const int TYPE_MISMATCH_ERR = 11;
 
   @DomName('FileError.code')
@@ -9381,28 +9538,52 @@
 @DomName('FileException')
 class FileException native "FileException" {
 
+  @DomName('FileException.ABORT_ERR')
+  @DocsEditable
   static const int ABORT_ERR = 3;
 
+  @DomName('FileException.ENCODING_ERR')
+  @DocsEditable
   static const int ENCODING_ERR = 5;
 
+  @DomName('FileException.INVALID_MODIFICATION_ERR')
+  @DocsEditable
   static const int INVALID_MODIFICATION_ERR = 9;
 
+  @DomName('FileException.INVALID_STATE_ERR')
+  @DocsEditable
   static const int INVALID_STATE_ERR = 7;
 
+  @DomName('FileException.NOT_FOUND_ERR')
+  @DocsEditable
   static const int NOT_FOUND_ERR = 1;
 
+  @DomName('FileException.NOT_READABLE_ERR')
+  @DocsEditable
   static const int NOT_READABLE_ERR = 4;
 
+  @DomName('FileException.NO_MODIFICATION_ALLOWED_ERR')
+  @DocsEditable
   static const int NO_MODIFICATION_ALLOWED_ERR = 6;
 
+  @DomName('FileException.PATH_EXISTS_ERR')
+  @DocsEditable
   static const int PATH_EXISTS_ERR = 12;
 
+  @DomName('FileException.QUOTA_EXCEEDED_ERR')
+  @DocsEditable
   static const int QUOTA_EXCEEDED_ERR = 10;
 
+  @DomName('FileException.SECURITY_ERR')
+  @DocsEditable
   static const int SECURITY_ERR = 2;
 
+  @DomName('FileException.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 8;
 
+  @DomName('FileException.TYPE_MISMATCH_ERR')
+  @DocsEditable
   static const int TYPE_MISMATCH_ERR = 11;
 
   @DomName('FileException.code')
@@ -9428,14 +9609,18 @@
 
 @DocsEditable
 @DomName('FileList')
-class FileList extends Object with ListMixin<File>, ImmutableListMixin<File> implements JavaScriptIndexingBehavior, List<File> native "FileList" {
+class FileList extends Interceptor with ListMixin<File>, ImmutableListMixin<File> implements JavaScriptIndexingBehavior, List<File> native "FileList" {
 
   @DomName('FileList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  File operator[](int index) => JS("File", "#[#]", this, index);
-
+  File operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("File", "#[#]", this, index);
+  }
   void operator[]=(int index, File value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -9447,6 +9632,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  File get first {
+    if (this.length > 0) {
+      return JS('File', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  File get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('File', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  File get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('File', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  File elementAt(int index) => this[index];
   // -- end List<File> mixins.
 
   @DomName('FileList.item')
@@ -9493,10 +9703,16 @@
   }
   static FileReader _create_1() => JS('FileReader', 'new FileReader()');
 
+  @DomName('FileReader.DONE')
+  @DocsEditable
   static const int DONE = 2;
 
+  @DomName('FileReader.EMPTY')
+  @DocsEditable
   static const int EMPTY = 0;
 
+  @DomName('FileReader.LOADING')
+  @DocsEditable
   static const int LOADING = 1;
 
   @DomName('FileReader.error')
@@ -9634,10 +9850,16 @@
   @DocsEditable
   static const EventStreamProvider<ProgressEvent> writeStartEvent = const EventStreamProvider<ProgressEvent>('writestart');
 
+  @DomName('FileWriter.DONE')
+  @DocsEditable
   static const int DONE = 2;
 
+  @DomName('FileWriter.INIT')
+  @DocsEditable
   static const int INIT = 0;
 
+  @DomName('FileWriter.WRITING')
+  @DocsEditable
   static const int WRITING = 1;
 
   @DomName('FileWriter.error')
@@ -10225,14 +10447,18 @@
 
 @DocsEditable
 @DomName('HTMLAllCollection')
-class HtmlAllCollection extends Object with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "HTMLAllCollection" {
+class HtmlAllCollection extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "HTMLAllCollection" {
 
   @DomName('HTMLAllCollection.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Node operator[](int index) => JS("Node", "#[#]", this, index);
-
+  Node operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Node", "#[#]", this, index);
+  }
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -10244,6 +10470,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return JS('Node', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Node', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Node', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @DomName('HTMLAllCollection.item')
@@ -10267,14 +10518,18 @@
 
 @DocsEditable
 @DomName('HTMLCollection')
-class HtmlCollection extends Object with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "HTMLCollection" {
+class HtmlCollection extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "HTMLCollection" {
 
   @DomName('HTMLCollection.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Node operator[](int index) => JS("Node", "#[#]", this, index);
-
+  Node operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Node", "#[#]", this, index);
+  }
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -10286,6 +10541,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return JS('Node', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Node', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Node', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @DomName('HTMLCollection.item')
@@ -10574,7 +10854,8 @@
    * See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access_authentication).
    */
   static Future<HttpRequest> request(String url,
-      {String method, bool withCredentials, String responseType, sendData,
+      {String method, bool withCredentials, String responseType,
+      String mimeType, Map<String, String> requestHeaders, sendData,
       void onProgress(ProgressEvent e)}) {
     var completer = new Completer<HttpRequest>();
 
@@ -10592,6 +10873,16 @@
       xhr.responseType = responseType;
     }
 
+    if (mimeType != null) {
+      xhr.overrideMimeType(mimeType);
+    }
+
+    if (requestHeaders != null) {
+      requestHeaders.forEach((header, value) {
+        xhr.setRequestHeader(header, value);
+      });
+    }
+
     if (onProgress != null) {
       xhr.onProgress.listen(onProgress);
     }
@@ -10647,6 +10938,15 @@
     return JS('bool', '("onloadend" in #)', xhr);
   }
 
+  /**
+   * Checks to see if the overrideMimeType method is supported on the current
+   * platform.
+   */
+  static bool get supportsOverrideMimeType {
+    var xhr = new HttpRequest();
+    return JS('bool', '("overrideMimeType" in #)', xhr);
+  }
+
 
   @DomName('XMLHttpRequest.abortEvent')
   @DocsEditable
@@ -10697,14 +10997,24 @@
   }
   static HttpRequest _create_1() => JS('HttpRequest', 'new XMLHttpRequest()');
 
+  @DomName('XMLHttpRequest.DONE')
+  @DocsEditable
   static const int DONE = 4;
 
+  @DomName('XMLHttpRequest.HEADERS_RECEIVED')
+  @DocsEditable
   static const int HEADERS_RECEIVED = 2;
 
+  @DomName('XMLHttpRequest.LOADING')
+  @DocsEditable
   static const int LOADING = 3;
 
+  @DomName('XMLHttpRequest.OPENED')
+  @DocsEditable
   static const int OPENED = 1;
 
+  @DomName('XMLHttpRequest.UNSENT')
+  @DocsEditable
   static const int UNSENT = 0;
 
   /**
@@ -10893,6 +11203,9 @@
    */
   @DomName('XMLHttpRequest.overrideMimeType')
   @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
   void overrideMimeType(String override) native;
 
   @JSName('removeEventListener')
@@ -10993,8 +11306,12 @@
 @DomName('XMLHttpRequestException')
 class HttpRequestException native "XMLHttpRequestException" {
 
+  @DomName('XMLHttpRequestException.ABORT_ERR')
+  @DocsEditable
   static const int ABORT_ERR = 102;
 
+  @DomName('XMLHttpRequestException.NETWORK_ERR')
+  @DocsEditable
   static const int NETWORK_ERR = 101;
 
   @DomName('XMLHttpRequestException.code')
@@ -12751,22 +13068,40 @@
   @Experimental
   static const EventStreamProvider<MediaKeyEvent> needKeyEvent = const EventStreamProvider<MediaKeyEvent>('webkitneedkey');
 
+  @DomName('HTMLMediaElement.HAVE_CURRENT_DATA')
+  @DocsEditable
   static const int HAVE_CURRENT_DATA = 2;
 
+  @DomName('HTMLMediaElement.HAVE_ENOUGH_DATA')
+  @DocsEditable
   static const int HAVE_ENOUGH_DATA = 4;
 
+  @DomName('HTMLMediaElement.HAVE_FUTURE_DATA')
+  @DocsEditable
   static const int HAVE_FUTURE_DATA = 3;
 
+  @DomName('HTMLMediaElement.HAVE_METADATA')
+  @DocsEditable
   static const int HAVE_METADATA = 1;
 
+  @DomName('HTMLMediaElement.HAVE_NOTHING')
+  @DocsEditable
   static const int HAVE_NOTHING = 0;
 
+  @DomName('HTMLMediaElement.NETWORK_EMPTY')
+  @DocsEditable
   static const int NETWORK_EMPTY = 0;
 
+  @DomName('HTMLMediaElement.NETWORK_IDLE')
+  @DocsEditable
   static const int NETWORK_IDLE = 1;
 
+  @DomName('HTMLMediaElement.NETWORK_LOADING')
+  @DocsEditable
   static const int NETWORK_LOADING = 2;
 
+  @DomName('HTMLMediaElement.NETWORK_NO_SOURCE')
+  @DocsEditable
   static const int NETWORK_NO_SOURCE = 3;
 
   @DomName('HTMLMediaElement.autoplay')
@@ -13070,14 +13405,24 @@
 @DomName('MediaError')
 class MediaError native "MediaError" {
 
+  @DomName('MediaError.MEDIA_ERR_ABORTED')
+  @DocsEditable
   static const int MEDIA_ERR_ABORTED = 1;
 
+  @DomName('MediaError.MEDIA_ERR_DECODE')
+  @DocsEditable
   static const int MEDIA_ERR_DECODE = 3;
 
+  @DomName('MediaError.MEDIA_ERR_ENCRYPTED')
+  @DocsEditable
   static const int MEDIA_ERR_ENCRYPTED = 5;
 
+  @DomName('MediaError.MEDIA_ERR_NETWORK')
+  @DocsEditable
   static const int MEDIA_ERR_NETWORK = 2;
 
+  @DomName('MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED')
+  @DocsEditable
   static const int MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
 
   @DomName('MediaError.code')
@@ -13093,16 +13438,28 @@
 @DomName('MediaKeyError')
 class MediaKeyError native "MediaKeyError" {
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_CLIENT')
+  @DocsEditable
   static const int MEDIA_KEYERR_CLIENT = 2;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_DOMAIN')
+  @DocsEditable
   static const int MEDIA_KEYERR_DOMAIN = 6;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_HARDWARECHANGE')
+  @DocsEditable
   static const int MEDIA_KEYERR_HARDWARECHANGE = 5;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_OUTPUT')
+  @DocsEditable
   static const int MEDIA_KEYERR_OUTPUT = 4;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_SERVICE')
+  @DocsEditable
   static const int MEDIA_KEYERR_SERVICE = 3;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_UNKNOWN')
+  @DocsEditable
   static const int MEDIA_KEYERR_UNKNOWN = 1;
 
   @DomName('MediaKeyError.code')
@@ -13806,14 +14163,18 @@
 
 @DocsEditable
 @DomName('MimeTypeArray')
-class MimeTypeArray extends Object with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements JavaScriptIndexingBehavior, List<MimeType> native "MimeTypeArray" {
+class MimeTypeArray extends Interceptor with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements JavaScriptIndexingBehavior, List<MimeType> native "MimeTypeArray" {
 
   @DomName('MimeTypeArray.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  MimeType operator[](int index) => JS("MimeType", "#[#]", this, index);
-
+  MimeType operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("MimeType", "#[#]", this, index);
+  }
   void operator[]=(int index, MimeType value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -13825,6 +14186,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  MimeType get first {
+    if (this.length > 0) {
+      return JS('MimeType', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  MimeType get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('MimeType', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  MimeType get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('MimeType', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  MimeType elementAt(int index) => this[index];
   // -- end List<MimeType> mixins.
 
   @DomName('MimeTypeArray.item')
@@ -14045,10 +14431,16 @@
     return event;
   }
 
+  @DomName('MutationEvent.ADDITION')
+  @DocsEditable
   static const int ADDITION = 2;
 
+  @DomName('MutationEvent.MODIFICATION')
+  @DocsEditable
   static const int MODIFICATION = 1;
 
+  @DomName('MutationEvent.REMOVAL')
+  @DocsEditable
   static const int REMOVAL = 3;
 
   @DomName('MutationEvent.attrChange')
@@ -14496,6 +14888,8 @@
 @DomName('NavigatorUserMediaError')
 class NavigatorUserMediaError native "NavigatorUserMediaError" {
 
+  @DomName('NavigatorUserMediaError.PERMISSION_DENIED')
+  @DocsEditable
   static const int PERMISSION_DENIED = 1;
 
   @DomName('NavigatorUserMediaError.code')
@@ -14780,28 +15174,52 @@
       (parent != null ? parent.templateInstance : null);
 
 
+  @DomName('Node.ATTRIBUTE_NODE')
+  @DocsEditable
   static const int ATTRIBUTE_NODE = 2;
 
+  @DomName('Node.CDATA_SECTION_NODE')
+  @DocsEditable
   static const int CDATA_SECTION_NODE = 4;
 
+  @DomName('Node.COMMENT_NODE')
+  @DocsEditable
   static const int COMMENT_NODE = 8;
 
+  @DomName('Node.DOCUMENT_FRAGMENT_NODE')
+  @DocsEditable
   static const int DOCUMENT_FRAGMENT_NODE = 11;
 
+  @DomName('Node.DOCUMENT_NODE')
+  @DocsEditable
   static const int DOCUMENT_NODE = 9;
 
+  @DomName('Node.DOCUMENT_TYPE_NODE')
+  @DocsEditable
   static const int DOCUMENT_TYPE_NODE = 10;
 
+  @DomName('Node.ELEMENT_NODE')
+  @DocsEditable
   static const int ELEMENT_NODE = 1;
 
+  @DomName('Node.ENTITY_NODE')
+  @DocsEditable
   static const int ENTITY_NODE = 6;
 
+  @DomName('Node.ENTITY_REFERENCE_NODE')
+  @DocsEditable
   static const int ENTITY_REFERENCE_NODE = 5;
 
+  @DomName('Node.NOTATION_NODE')
+  @DocsEditable
   static const int NOTATION_NODE = 12;
 
+  @DomName('Node.PROCESSING_INSTRUCTION_NODE')
+  @DocsEditable
   static const int PROCESSING_INSTRUCTION_NODE = 7;
 
+  @DomName('Node.TEXT_NODE')
+  @DocsEditable
   static const int TEXT_NODE = 3;
 
   @JSName('childNodes')
@@ -14873,6 +15291,15 @@
   void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native;
 
   @JSName('appendChild')
+  /**
+   * Adds a node to the end of the child [nodes] list of this node.
+   *
+   * If the node already exists in this document, it will be removed from its
+   * current parent node, then added to this node.
+   *
+   * This method is more efficient than `nodes.add`, and is the preferred
+   * way of appending a child node.
+   */
   @DomName('Node.appendChild')
   @DocsEditable
   Node append(Node newChild) native;
@@ -14923,36 +15350,68 @@
 @DomName('NodeFilter')
 class NodeFilter native "NodeFilter" {
 
+  @DomName('NodeFilter.FILTER_ACCEPT')
+  @DocsEditable
   static const int FILTER_ACCEPT = 1;
 
+  @DomName('NodeFilter.FILTER_REJECT')
+  @DocsEditable
   static const int FILTER_REJECT = 2;
 
+  @DomName('NodeFilter.FILTER_SKIP')
+  @DocsEditable
   static const int FILTER_SKIP = 3;
 
+  @DomName('NodeFilter.SHOW_ALL')
+  @DocsEditable
   static const int SHOW_ALL = 0xFFFFFFFF;
 
+  @DomName('NodeFilter.SHOW_ATTRIBUTE')
+  @DocsEditable
   static const int SHOW_ATTRIBUTE = 0x00000002;
 
+  @DomName('NodeFilter.SHOW_CDATA_SECTION')
+  @DocsEditable
   static const int SHOW_CDATA_SECTION = 0x00000008;
 
+  @DomName('NodeFilter.SHOW_COMMENT')
+  @DocsEditable
   static const int SHOW_COMMENT = 0x00000080;
 
+  @DomName('NodeFilter.SHOW_DOCUMENT')
+  @DocsEditable
   static const int SHOW_DOCUMENT = 0x00000100;
 
+  @DomName('NodeFilter.SHOW_DOCUMENT_FRAGMENT')
+  @DocsEditable
   static const int SHOW_DOCUMENT_FRAGMENT = 0x00000400;
 
+  @DomName('NodeFilter.SHOW_DOCUMENT_TYPE')
+  @DocsEditable
   static const int SHOW_DOCUMENT_TYPE = 0x00000200;
 
+  @DomName('NodeFilter.SHOW_ELEMENT')
+  @DocsEditable
   static const int SHOW_ELEMENT = 0x00000001;
 
+  @DomName('NodeFilter.SHOW_ENTITY')
+  @DocsEditable
   static const int SHOW_ENTITY = 0x00000020;
 
+  @DomName('NodeFilter.SHOW_ENTITY_REFERENCE')
+  @DocsEditable
   static const int SHOW_ENTITY_REFERENCE = 0x00000010;
 
+  @DomName('NodeFilter.SHOW_NOTATION')
+  @DocsEditable
   static const int SHOW_NOTATION = 0x00000800;
 
+  @DomName('NodeFilter.SHOW_PROCESSING_INSTRUCTION')
+  @DocsEditable
   static const int SHOW_PROCESSING_INSTRUCTION = 0x00000040;
 
+  @DomName('NodeFilter.SHOW_TEXT')
+  @DocsEditable
   static const int SHOW_TEXT = 0x00000004;
 }
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
@@ -15002,14 +15461,18 @@
 
 @DocsEditable
 @DomName('NodeList')
-class NodeList extends Object with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NodeList,RadioNodeList" {
+class NodeList extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NodeList,RadioNodeList" {
 
   @DomName('NodeList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Node operator[](int index) => JS("Node", "#[#]", this, index);
-
+  Node operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Node", "#[#]", this, index);
+  }
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -15021,6 +15484,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return JS('Node', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Node', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Node', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @JSName('item')
@@ -15481,10 +15969,16 @@
 @DomName('OverflowEvent')
 class OverflowEvent extends Event native "OverflowEvent" {
 
+  @DomName('OverflowEvent.BOTH')
+  @DocsEditable
   static const int BOTH = 2;
 
+  @DomName('OverflowEvent.HORIZONTAL')
+  @DocsEditable
   static const int HORIZONTAL = 0;
 
+  @DomName('OverflowEvent.VERTICAL')
+  @DocsEditable
   static const int VERTICAL = 1;
 
   @DomName('OverflowEvent.horizontalOverflow')
@@ -15777,12 +16271,20 @@
 @DomName('PerformanceNavigation')
 class PerformanceNavigation native "PerformanceNavigation" {
 
+  @DomName('PerformanceNavigation.TYPE_BACK_FORWARD')
+  @DocsEditable
   static const int TYPE_BACK_FORWARD = 2;
 
+  @DomName('PerformanceNavigation.TYPE_NAVIGATE')
+  @DocsEditable
   static const int TYPE_NAVIGATE = 0;
 
+  @DomName('PerformanceNavigation.TYPE_RELOAD')
+  @DocsEditable
   static const int TYPE_RELOAD = 1;
 
+  @DomName('PerformanceNavigation.TYPE_RESERVED')
+  @DocsEditable
   static const int TYPE_RESERVED = 255;
 
   @DomName('PerformanceNavigation.redirectCount')
@@ -15983,14 +16485,18 @@
 
 @DocsEditable
 @DomName('PluginArray')
-class PluginArray extends Object with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements JavaScriptIndexingBehavior, List<Plugin> native "PluginArray" {
+class PluginArray extends Interceptor with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements JavaScriptIndexingBehavior, List<Plugin> native "PluginArray" {
 
   @DomName('PluginArray.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Plugin operator[](int index) => JS("Plugin", "#[#]", this, index);
-
+  Plugin operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Plugin", "#[#]", this, index);
+  }
   void operator[]=(int index, Plugin value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -16002,6 +16508,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Plugin get first {
+    if (this.length > 0) {
+      return JS('Plugin', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Plugin get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Plugin', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Plugin get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Plugin', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Plugin elementAt(int index) => this[index];
   // -- end List<Plugin> mixins.
 
   @DomName('PluginArray.item')
@@ -16054,10 +16585,16 @@
 @DomName('PositionError')
 class PositionError native "PositionError" {
 
+  @DomName('PositionError.PERMISSION_DENIED')
+  @DocsEditable
   static const int PERMISSION_DENIED = 1;
 
+  @DomName('PositionError.POSITION_UNAVAILABLE')
+  @DocsEditable
   static const int POSITION_UNAVAILABLE = 2;
 
+  @DomName('PositionError.TIMEOUT')
+  @DocsEditable
   static const int TIMEOUT = 3;
 
   @DomName('PositionError.code')
@@ -16222,20 +16759,36 @@
   factory Range() => document.$dom_createRange();
 
 
+  @DomName('Range.END_TO_END')
+  @DocsEditable
   static const int END_TO_END = 2;
 
+  @DomName('Range.END_TO_START')
+  @DocsEditable
   static const int END_TO_START = 3;
 
+  @DomName('Range.NODE_AFTER')
+  @DocsEditable
   static const int NODE_AFTER = 1;
 
+  @DomName('Range.NODE_BEFORE')
+  @DocsEditable
   static const int NODE_BEFORE = 0;
 
+  @DomName('Range.NODE_BEFORE_AND_AFTER')
+  @DocsEditable
   static const int NODE_BEFORE_AND_AFTER = 2;
 
+  @DomName('Range.NODE_INSIDE')
+  @DocsEditable
   static const int NODE_INSIDE = 3;
 
+  @DomName('Range.START_TO_END')
+  @DocsEditable
   static const int START_TO_END = 1;
 
+  @DomName('Range.START_TO_START')
+  @DocsEditable
   static const int START_TO_START = 0;
 
   @DomName('Range.collapsed')
@@ -16384,8 +16937,12 @@
 @DomName('RangeException')
 class RangeException native "RangeException" {
 
+  @DomName('RangeException.BAD_BOUNDARYPOINTS_ERR')
+  @DocsEditable
   static const int BAD_BOUNDARYPOINTS_ERR = 1;
 
+  @DomName('RangeException.INVALID_NODE_TYPE_ERR')
+  @DocsEditable
   static const int INVALID_NODE_TYPE_ERR = 2;
 
   @DomName('RangeException.code')
@@ -17644,8 +18201,12 @@
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  SourceBuffer operator[](int index) => JS("SourceBuffer", "#[#]", this, index);
-
+  SourceBuffer operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("SourceBuffer", "#[#]", this, index);
+  }
   void operator[]=(int index, SourceBuffer value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -17657,6 +18218,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SourceBuffer get first {
+    if (this.length > 0) {
+      return JS('SourceBuffer', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  SourceBuffer get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('SourceBuffer', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  SourceBuffer get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('SourceBuffer', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SourceBuffer elementAt(int index) => this[index];
   // -- end List<SourceBuffer> mixins.
 
   @JSName('addEventListener')
@@ -17746,7 +18332,7 @@
 
 @DocsEditable
 @DomName('SpeechGrammarList')
-class SpeechGrammarList extends Object with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements JavaScriptIndexingBehavior, List<SpeechGrammar> native "SpeechGrammarList" {
+class SpeechGrammarList extends Interceptor with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements JavaScriptIndexingBehavior, List<SpeechGrammar> native "SpeechGrammarList" {
 
   @DomName('SpeechGrammarList.SpeechGrammarList')
   @DocsEditable
@@ -17759,8 +18345,12 @@
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  SpeechGrammar operator[](int index) => JS("SpeechGrammar", "#[#]", this, index);
-
+  SpeechGrammar operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("SpeechGrammar", "#[#]", this, index);
+  }
   void operator[]=(int index, SpeechGrammar value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -17772,6 +18362,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SpeechGrammar get first {
+    if (this.length > 0) {
+      return JS('SpeechGrammar', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechGrammar get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('SpeechGrammar', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechGrammar get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('SpeechGrammar', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SpeechGrammar elementAt(int index) => this[index];
   // -- end List<SpeechGrammar> mixins.
 
   @DomName('SpeechGrammarList.addFromString')
@@ -18233,8 +18848,12 @@
 @DomName('StorageInfo')
 class StorageInfo native "StorageInfo" {
 
+  @DomName('StorageInfo.PERSISTENT')
+  @DocsEditable
   static const int PERSISTENT = 1;
 
+  @DomName('StorageInfo.TEMPORARY')
+  @DocsEditable
   static const int TEMPORARY = 0;
 
   @JSName('queryUsageAndQuota')
@@ -18723,7 +19342,7 @@
 
     // Create content
     if (template is! TemplateElement) {
-      var doc = _getTemplateContentsOwner(template.document);
+      var doc = _Bindings._getTemplateContentsOwner(template.document);
       template._templateContent = doc.createDocumentFragment();
     }
 
@@ -18733,9 +19352,9 @@
     }
 
     if (template is TemplateElement) {
-      _bootstrapTemplatesRecursivelyFrom(template.content);
+      bootstrap(template.content);
     } else {
-      _liftNonNativeTemplateChildrenIntoContent(template);
+      _Bindings._liftNonNativeChildrenIntoContent(template);
     }
 
     return true;
@@ -18751,7 +19370,23 @@
   // TODO(rafaelw): Review whether this is the right public API.
   @Experimental
   static void bootstrap(Node content) {
-    _bootstrapTemplatesRecursivelyFrom(content);
+    _Bindings._bootstrapTemplatesRecursivelyFrom(content);
+  }
+
+  /**
+   * Binds all mustaches recursively starting from the [root] node.
+   *
+   * Note: this is not an official Model-Driven-Views API; it is intended to
+   * support binding the [ShadowRoot]'s content to a model.
+   */
+  // TODO(jmesserly): this is needed to avoid two <template> nodes when using
+  // bindings in a custom element's template. See also:
+  // https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
+  // Called from:
+  // https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
+  @Experimental
+  static void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
+    _Bindings._addBindings(root, model, syntax);
   }
 
   static bool _initStyles;
@@ -19191,14 +19826,18 @@
 
 @DocsEditable
 @DomName('TextTrackCueList')
-class TextTrackCueList extends Object with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List<TextTrackCue>, JavaScriptIndexingBehavior native "TextTrackCueList" {
+class TextTrackCueList extends Interceptor with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List<TextTrackCue>, JavaScriptIndexingBehavior native "TextTrackCueList" {
 
   @DomName('TextTrackCueList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  TextTrackCue operator[](int index) => JS("TextTrackCue", "#[#]", this, index);
-
+  TextTrackCue operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("TextTrackCue", "#[#]", this, index);
+  }
   void operator[]=(int index, TextTrackCue value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -19210,6 +19849,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  TextTrackCue get first {
+    if (this.length > 0) {
+      return JS('TextTrackCue', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrackCue get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('TextTrackCue', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrackCue get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('TextTrackCue', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  TextTrackCue elementAt(int index) => this[index];
   // -- end List<TextTrackCue> mixins.
 
   @DomName('TextTrackCueList.getCueById')
@@ -19237,8 +19901,12 @@
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  TextTrack operator[](int index) => JS("TextTrack", "#[#]", this, index);
-
+  TextTrack operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("TextTrack", "#[#]", this, index);
+  }
   void operator[]=(int index, TextTrack value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -19250,6 +19918,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  TextTrack get first {
+    if (this.length > 0) {
+      return JS('TextTrack', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrack get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('TextTrack', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrack get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('TextTrack', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  TextTrack elementAt(int index) => this[index];
   // -- end List<TextTrack> mixins.
 
   @JSName('addEventListener')
@@ -19490,7 +20183,7 @@
 
 
 @DomName('TouchList')
-class TouchList extends Object with ListMixin<Touch>, ImmutableListMixin<Touch> implements JavaScriptIndexingBehavior, List<Touch> native "TouchList" {
+class TouchList extends Interceptor with ListMixin<Touch>, ImmutableListMixin<Touch> implements JavaScriptIndexingBehavior, List<Touch> native "TouchList" {
   /// NB: This constructor likely does not work as you might expect it to! This
   /// constructor will simply fail (returning null) if you are not on a device
   /// with touch enabled. See dartbug.com/8314.
@@ -19503,8 +20196,12 @@
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Touch operator[](int index) => JS("Touch", "#[#]", this, index);
-
+  Touch operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Touch", "#[#]", this, index);
+  }
   void operator[]=(int index, Touch value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -19516,6 +20213,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Touch get first {
+    if (this.length > 0) {
+      return JS('Touch', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Touch get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Touch', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Touch get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Touch', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Touch elementAt(int index) => this[index];
   // -- end List<Touch> mixins.
 
   @DomName('TouchList.item')
@@ -19542,12 +20264,20 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => Element.isTagSupported('track');
 
+  @DomName('HTMLTrackElement.ERROR')
+  @DocsEditable
   static const int ERROR = 3;
 
+  @DomName('HTMLTrackElement.LOADED')
+  @DocsEditable
   static const int LOADED = 2;
 
+  @DomName('HTMLTrackElement.LOADING')
+  @DocsEditable
   static const int LOADING = 1;
 
+  @DomName('HTMLTrackElement.NONE')
+  @DocsEditable
   static const int NONE = 0;
 
   @JSName('default')
@@ -19801,12 +20531,12 @@
 
   static String createObjectUrl(blob_OR_source_OR_stream) =>
       JS('String',
-         '(window.URL || window.webkitURL).createObjectURL(#)',
+         '(self.URL || self.webkitURL).createObjectURL(#)',
          blob_OR_source_OR_stream);
 
   static void revokeObjectUrl(String objectUrl) =>
       JS('void',
-         '(window.URL || window.webkitURL).revokeObjectURL(#)', objectUrl);
+         '(self.URL || self.webkitURL).revokeObjectURL(#)', objectUrl);
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -20047,12 +20777,20 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => JS('bool', 'typeof window.WebSocket != "undefined"');
 
+  @DomName('WebSocket.CLOSED')
+  @DocsEditable
   static const int CLOSED = 3;
 
+  @DomName('WebSocket.CLOSING')
+  @DocsEditable
   static const int CLOSING = 2;
 
+  @DomName('WebSocket.CONNECTING')
+  @DocsEditable
   static const int CONNECTING = 0;
 
+  @DomName('WebSocket.OPEN')
+  @DocsEditable
   static const int OPEN = 1;
 
   @JSName('URL')
@@ -20201,10 +20939,16 @@
   }
 
 
+  @DomName('WheelEvent.DOM_DELTA_LINE')
+  @DocsEditable
   static const int DOM_DELTA_LINE = 0x01;
 
+  @DomName('WheelEvent.DOM_DELTA_PAGE')
+  @DocsEditable
   static const int DOM_DELTA_PAGE = 0x02;
 
+  @DomName('WheelEvent.DOM_DELTA_PIXEL')
+  @DocsEditable
   static const int DOM_DELTA_PIXEL = 0x00;
 
   @JSName('webkitDirectionInvertedFromDevice')
@@ -20678,8 +21422,12 @@
   @Experimental
   static const EventStreamProvider<AnimationEvent> animationStartEvent = const EventStreamProvider<AnimationEvent>('webkitAnimationStart');
 
+  @DomName('Window.PERSISTENT')
+  @DocsEditable
   static const int PERSISTENT = 1;
 
+  @DomName('Window.TEMPORARY')
+  @DocsEditable
   static const int TEMPORARY = 0;
 
   @DomName('Window.applicationCache')
@@ -21449,8 +22197,12 @@
 @DomName('XPathException')
 class XPathException native "XPathException" {
 
+  @DomName('XPathException.INVALID_EXPRESSION_ERR')
+  @DocsEditable
   static const int INVALID_EXPRESSION_ERR = 51;
 
+  @DomName('XPathException.TYPE_ERR')
+  @DocsEditable
   static const int TYPE_ERR = 52;
 
   @DomName('XPathException.code')
@@ -21505,24 +22257,44 @@
 @DomName('XPathResult')
 class XPathResult native "XPathResult" {
 
+  @DomName('XPathResult.ANY_TYPE')
+  @DocsEditable
   static const int ANY_TYPE = 0;
 
+  @DomName('XPathResult.ANY_UNORDERED_NODE_TYPE')
+  @DocsEditable
   static const int ANY_UNORDERED_NODE_TYPE = 8;
 
+  @DomName('XPathResult.BOOLEAN_TYPE')
+  @DocsEditable
   static const int BOOLEAN_TYPE = 3;
 
+  @DomName('XPathResult.FIRST_ORDERED_NODE_TYPE')
+  @DocsEditable
   static const int FIRST_ORDERED_NODE_TYPE = 9;
 
+  @DomName('XPathResult.NUMBER_TYPE')
+  @DocsEditable
   static const int NUMBER_TYPE = 1;
 
+  @DomName('XPathResult.ORDERED_NODE_ITERATOR_TYPE')
+  @DocsEditable
   static const int ORDERED_NODE_ITERATOR_TYPE = 5;
 
+  @DomName('XPathResult.ORDERED_NODE_SNAPSHOT_TYPE')
+  @DocsEditable
   static const int ORDERED_NODE_SNAPSHOT_TYPE = 7;
 
+  @DomName('XPathResult.STRING_TYPE')
+  @DocsEditable
   static const int STRING_TYPE = 2;
 
+  @DomName('XPathResult.UNORDERED_NODE_ITERATOR_TYPE')
+  @DocsEditable
   static const int UNORDERED_NODE_ITERATOR_TYPE = 4;
 
+  @DomName('XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE')
+  @DocsEditable
   static const int UNORDERED_NODE_SNAPSHOT_TYPE = 6;
 
   @DomName('XPathResult.booleanValue')
@@ -21785,14 +22557,18 @@
 
 @DocsEditable
 @DomName('ClientRectList')
-class _ClientRectList extends Object with ListMixin<Rect>, ImmutableListMixin<Rect> implements JavaScriptIndexingBehavior, List<Rect> native "ClientRectList" {
+class _ClientRectList extends Interceptor with ListMixin<Rect>, ImmutableListMixin<Rect> implements JavaScriptIndexingBehavior, List<Rect> native "ClientRectList" {
 
   @DomName('ClientRectList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Rect operator[](int index) => JS("Rect", "#[#]", this, index);
-
+  Rect operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Rect", "#[#]", this, index);
+  }
   void operator[]=(int index, Rect value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -21804,6 +22580,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Rect get first {
+    if (this.length > 0) {
+      return JS('Rect', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Rect get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Rect', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Rect get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Rect', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Rect elementAt(int index) => this[index];
   // -- end List<Rect> mixins.
 
   @DomName('ClientRectList.item')
@@ -21826,14 +22627,18 @@
 
 @DocsEditable
 @DomName('CSSRuleList')
-class _CssRuleList extends Object with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements JavaScriptIndexingBehavior, List<CssRule> native "CSSRuleList" {
+class _CssRuleList extends Interceptor with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements JavaScriptIndexingBehavior, List<CssRule> native "CSSRuleList" {
 
   @DomName('CSSRuleList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  CssRule operator[](int index) => JS("CssRule", "#[#]", this, index);
-
+  CssRule operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("CssRule", "#[#]", this, index);
+  }
   void operator[]=(int index, CssRule value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -21845,6 +22650,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  CssRule get first {
+    if (this.length > 0) {
+      return JS('CssRule', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  CssRule get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('CssRule', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  CssRule get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('CssRule', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  CssRule elementAt(int index) => this[index];
   // -- end List<CssRule> mixins.
 
   @DomName('CSSRuleList.item')
@@ -21864,8 +22694,12 @@
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  _CSSValue operator[](int index) => JS("_CSSValue", "#[#]", this, index);
-
+  _CSSValue operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("_CSSValue", "#[#]", this, index);
+  }
   void operator[]=(int index, _CSSValue value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -21877,6 +22711,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  _CSSValue get first {
+    if (this.length > 0) {
+      return JS('_CSSValue', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  _CSSValue get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('_CSSValue', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  _CSSValue get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('_CSSValue', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  _CSSValue elementAt(int index) => this[index];
   // -- end List<_CSSValue> mixins.
 
   @DomName('CSSValueList.item')
@@ -21979,14 +22838,18 @@
 
 @DocsEditable
 @DomName('EntryArray')
-class _EntryArray extends Object with ListMixin<Entry>, ImmutableListMixin<Entry> implements JavaScriptIndexingBehavior, List<Entry> native "EntryArray" {
+class _EntryArray extends Interceptor with ListMixin<Entry>, ImmutableListMixin<Entry> implements JavaScriptIndexingBehavior, List<Entry> native "EntryArray" {
 
   @DomName('EntryArray.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Entry operator[](int index) => JS("Entry", "#[#]", this, index);
-
+  Entry operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Entry", "#[#]", this, index);
+  }
   void operator[]=(int index, Entry value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -21998,6 +22861,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Entry get first {
+    if (this.length > 0) {
+      return JS('Entry', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Entry get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Entry', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Entry get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Entry', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Entry elementAt(int index) => this[index];
   // -- end List<Entry> mixins.
 
   @DomName('EntryArray.item')
@@ -22011,14 +22899,18 @@
 
 @DocsEditable
 @DomName('EntryArraySync')
-class _EntryArraySync extends Object with ListMixin<_EntrySync>, ImmutableListMixin<_EntrySync> implements JavaScriptIndexingBehavior, List<_EntrySync> native "EntryArraySync" {
+class _EntryArraySync extends Interceptor with ListMixin<_EntrySync>, ImmutableListMixin<_EntrySync> implements JavaScriptIndexingBehavior, List<_EntrySync> native "EntryArraySync" {
 
   @DomName('EntryArraySync.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  _EntrySync operator[](int index) => JS("_EntrySync", "#[#]", this, index);
-
+  _EntrySync operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("_EntrySync", "#[#]", this, index);
+  }
   void operator[]=(int index, _EntrySync value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -22030,6 +22922,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  _EntrySync get first {
+    if (this.length > 0) {
+      return JS('_EntrySync', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  _EntrySync get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('_EntrySync', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  _EntrySync get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('_EntrySync', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  _EntrySync elementAt(int index) => this[index];
   // -- end List<_EntrySync> mixins.
 
   @DomName('EntryArraySync.item')
@@ -22086,14 +23003,18 @@
 
 @DocsEditable
 @DomName('GamepadList')
-class _GamepadList extends Object with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements JavaScriptIndexingBehavior, List<Gamepad> native "GamepadList" {
+class _GamepadList extends Interceptor with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements JavaScriptIndexingBehavior, List<Gamepad> native "GamepadList" {
 
   @DomName('GamepadList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Gamepad operator[](int index) => JS("Gamepad", "#[#]", this, index);
-
+  Gamepad operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Gamepad", "#[#]", this, index);
+  }
   void operator[]=(int index, Gamepad value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -22105,6 +23026,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Gamepad get first {
+    if (this.length > 0) {
+      return JS('Gamepad', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Gamepad get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Gamepad', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Gamepad get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Gamepad', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Gamepad elementAt(int index) => this[index];
   // -- end List<Gamepad> mixins.
 
   @DomName('GamepadList.item')
@@ -22181,14 +23127,18 @@
 
 @DocsEditable
 @DomName('NamedNodeMap')
-class _NamedNodeMap extends Object with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NamedNodeMap" {
+class _NamedNodeMap extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NamedNodeMap" {
 
   @DomName('NamedNodeMap.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Node operator[](int index) => JS("Node", "#[#]", this, index);
-
+  Node operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("Node", "#[#]", this, index);
+  }
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -22200,6 +23150,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return JS('Node', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Node', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Node', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @DomName('NamedNodeMap.getNamedItem')
@@ -22302,14 +23277,18 @@
 
 @DocsEditable
 @DomName('SpeechInputResultList')
-class _SpeechInputResultList extends Object with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements JavaScriptIndexingBehavior, List<SpeechInputResult> native "SpeechInputResultList" {
+class _SpeechInputResultList extends Interceptor with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements JavaScriptIndexingBehavior, List<SpeechInputResult> native "SpeechInputResultList" {
 
   @DomName('SpeechInputResultList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  SpeechInputResult operator[](int index) => JS("SpeechInputResult", "#[#]", this, index);
-
+  SpeechInputResult operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("SpeechInputResult", "#[#]", this, index);
+  }
   void operator[]=(int index, SpeechInputResult value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -22321,6 +23300,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SpeechInputResult get first {
+    if (this.length > 0) {
+      return JS('SpeechInputResult', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechInputResult get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('SpeechInputResult', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechInputResult get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('SpeechInputResult', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SpeechInputResult elementAt(int index) => this[index];
   // -- end List<SpeechInputResult> mixins.
 
   @DomName('SpeechInputResultList.item')
@@ -22334,14 +23338,18 @@
 
 @DocsEditable
 @DomName('SpeechRecognitionResultList')
-class _SpeechRecognitionResultList extends Object with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements JavaScriptIndexingBehavior, List<SpeechRecognitionResult> native "SpeechRecognitionResultList" {
+class _SpeechRecognitionResultList extends Interceptor with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements JavaScriptIndexingBehavior, List<SpeechRecognitionResult> native "SpeechRecognitionResultList" {
 
   @DomName('SpeechRecognitionResultList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  SpeechRecognitionResult operator[](int index) => JS("SpeechRecognitionResult", "#[#]", this, index);
-
+  SpeechRecognitionResult operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("SpeechRecognitionResult", "#[#]", this, index);
+  }
   void operator[]=(int index, SpeechRecognitionResult value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -22353,6 +23361,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SpeechRecognitionResult get first {
+    if (this.length > 0) {
+      return JS('SpeechRecognitionResult', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechRecognitionResult get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('SpeechRecognitionResult', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechRecognitionResult get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('SpeechRecognitionResult', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SpeechRecognitionResult elementAt(int index) => this[index];
   // -- end List<SpeechRecognitionResult> mixins.
 
   @DomName('SpeechRecognitionResultList.item')
@@ -22366,14 +23399,18 @@
 
 @DocsEditable
 @DomName('StyleSheetList')
-class _StyleSheetList extends Object with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements JavaScriptIndexingBehavior, List<StyleSheet> native "StyleSheetList" {
+class _StyleSheetList extends Interceptor with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements JavaScriptIndexingBehavior, List<StyleSheet> native "StyleSheetList" {
 
   @DomName('StyleSheetList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  StyleSheet operator[](int index) => JS("StyleSheet", "#[#]", this, index);
-
+  StyleSheet operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return JS("StyleSheet", "#[#]", this, index);
+  }
   void operator[]=(int index, StyleSheet value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -22385,6 +23422,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  StyleSheet get first {
+    if (this.length > 0) {
+      return JS('StyleSheet', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  StyleSheet get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('StyleSheet', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  StyleSheet get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('StyleSheet', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  StyleSheet elementAt(int index) => this[index];
   // -- end List<StyleSheet> mixins.
 
   @DomName('StyleSheetList.item')
@@ -24935,7 +25997,7 @@
 
 
 // This code is a port of Model-Driven-Views:
-// https://github.com/toolkitchen/mdv
+// https://github.com/polymer-project/mdv
 // The code mostly comes from src/template_element.js
 
 typedef void _ChangeHandler(value);
@@ -24967,7 +26029,7 @@
  *
  *     TemplateElement.syntax['MySyntax'] = new MySyntax();
  *
- * See <https://github.com/toolkitchen/mdv/blob/master/docs/syntax.md> for more
+ * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for more
  * information about Custom Syntax.
  */
 // TODO(jmesserly): if this is just one method, a function type would make it
@@ -25176,19 +26238,6 @@
   }
 }
 
-Stream<Event> _getStreamForInputType(InputElement element) {
-  switch (element.type) {
-    case 'checkbox':
-      return element.onClick;
-    case 'radio':
-    case 'select-multiple':
-    case 'select-one':
-      return element.onChange;
-    default:
-      return element.onInput;
-  }
-}
-
 abstract class _InputBinding {
   final InputElement element;
   PathObserver binding;
@@ -25210,6 +26259,20 @@
     _pathSub.cancel();
     _eventSub.cancel();
   }
+
+
+  static Stream<Event> _getStreamForInputType(InputElement element) {
+    switch (element.type) {
+      case 'checkbox':
+        return element.onClick;
+      case 'radio':
+      case 'select-multiple':
+      case 'select-one':
+        return element.onChange;
+      default:
+        return element.onInput;
+    }
+  }
 }
 
 class _ValueBinding extends _InputBinding {
@@ -25224,18 +26287,11 @@
   }
 }
 
-// TODO(jmesserly): not sure what kind of boolean conversion rules to
-// apply for template data-binding. HTML attributes are true if they're present.
-// However Dart only treats "true" as true. Since this is HTML we'll use
-// something closer to the HTML rules: null (missing) and false are false,
-// everything else is true. See: https://github.com/toolkitchen/mdv/issues/59
-bool _templateBooleanConversion(value) => null != value && false != value;
-
 class _CheckedBinding extends _InputBinding {
   _CheckedBinding(element, model, path) : super(element, model, path);
 
   void valueChanged(value) {
-    element.checked = _templateBooleanConversion(value);
+    element.checked = _Bindings._toBoolean(value);
   }
 
   void updateBinding(e) {
@@ -25254,220 +26310,309 @@
       }
     }
   }
-}
 
-// TODO(jmesserly): polyfill document.contains API instead of doing it here
-bool _isNodeInDocument(Node node) {
-  // On non-IE this works:
-  // return node.document.contains(node);
-  var document = node.document;
-  if (node == document || node.parentNode == document) return true;
-  return document.documentElement.contains(node);
-}
-
-// |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
-// Returns an array containing all radio buttons other than |element| that
-// have the same |name|, either in the form that |element| belongs to or,
-// if no form, in the document tree to which |element| belongs.
-//
-// This implementation is based upon the HTML spec definition of a
-// "radio button group":
-//   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
-//
-Iterable _getAssociatedRadioButtons(element) {
-  if (!_isNodeInDocument(element)) return [];
-  if (element.form != null) {
-    return element.form.nodes.where((el) {
-      return el != element &&
-          el is InputElement &&
-          el.type == 'radio' &&
-          el.name == element.name;
-    });
-  } else {
-    var radios = element.document.queryAll(
-        'input[type="radio"][name="${element.name}"]');
-    return radios.where((el) => el != element && el.form == null);
-  }
-}
-
-Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
-  var clone = node.clone(false); // Shallow clone.
-  if (clone is Element && clone.isTemplate) {
-    TemplateElement.decorate(clone, node);
-    if (syntax != null) {
-      clone.attributes.putIfAbsent('syntax', () => syntax);
-    }
-  }
-
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
-  }
-  return clone;
-}
-
-// http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-Document _getTemplateContentsOwner(Document doc) {
-  if (doc.window == null) {
-    return doc;
-  }
-  var d = doc._templateContentsOwner;
-  if (d == null) {
-    // TODO(arv): This should either be a Document or HTMLDocument depending
-    // on doc.
-    d = doc.implementation.createHtmlDocument('');
-    while (d.$dom_lastChild != null) {
-      d.$dom_lastChild.remove();
-    }
-    doc._templateContentsOwner = d;
-  }
-  return d;
-}
-
-Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
-  var clone = templateElement.clone(false);
-  var attributes = templateElement.attributes;
-  for (var name in attributes.keys.toList()) {
-    switch (name) {
-      case 'template':
-      case 'repeat':
-      case 'bind':
-      case 'ref':
-        clone.attributes.remove(name);
-        break;
-      default:
-        attributes.remove(name);
-        break;
-    }
-  }
-
-  return clone;
-}
-
-void _liftNonNativeTemplateChildrenIntoContent(Element templateElement) {
-  var content = templateElement.content;
-
-  if (!templateElement._isAttributeTemplate) {
-    var child;
-    while ((child = templateElement.$dom_firstChild) != null) {
-      content.append(child);
-    }
-    return;
-  }
-
-  // For attribute templates we copy the whole thing into the content and
-  // we move the non template attributes into the content.
+  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
+  // Returns an array containing all radio buttons other than |element| that
+  // have the same |name|, either in the form that |element| belongs to or,
+  // if no form, in the document tree to which |element| belongs.
   //
-  //   <tr foo template>
+  // This implementation is based upon the HTML spec definition of a
+  // "radio button group":
+  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
   //
-  // becomes
-  //
-  //   <tr template>
-  //   + #document-fragment
-  //     + <tr foo>
-  //
-  var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
-  var child;
-  while ((child = templateElement.$dom_firstChild) != null) {
-    newRoot.append(child);
-  }
-  content.append(newRoot);
-}
-
-void _bootstrapTemplatesRecursivelyFrom(Node node) {
-  void bootstrap(template) {
-    if (!TemplateElement.decorate(template)) {
-      _bootstrapTemplatesRecursivelyFrom(template.content);
+  static Iterable _getAssociatedRadioButtons(element) {
+    if (!_isNodeInDocument(element)) return [];
+    if (element.form != null) {
+      return element.form.nodes.where((el) {
+        return el != element &&
+            el is InputElement &&
+            el.type == 'radio' &&
+            el.name == element.name;
+      });
+    } else {
+      var radios = element.document.queryAll(
+          'input[type="radio"][name="${element.name}"]');
+      return radios.where((el) => el != element && el.form == null);
     }
   }
 
-  // Need to do this first as the contents may get lifted if |node| is
-  // template.
-  // TODO(jmesserly): node is DocumentFragment or Element
-  var templateDescendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-  if (node is Element && node.isTemplate) bootstrap(node);
-
-  templateDescendents.forEach(bootstrap);
-}
-
-final String _allTemplatesSelectors = 'template, option[template], ' +
-    Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
-  if (node is Element) {
-    _addAttributeBindings(node, model, syntax);
-  } else if (node is Text) {
-    _parseAndBind(node, 'text', node.text, model, syntax);
-  }
-
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    _addBindings(c, model, syntax);
+  // TODO(jmesserly): polyfill document.contains API instead of doing it here
+  static bool _isNodeInDocument(Node node) {
+    // On non-IE this works:
+    // return node.document.contains(node);
+    var document = node.document;
+    if (node == document || node.parentNode == document) return true;
+    return document.documentElement.contains(node);
   }
 }
 
+class _Bindings {
+  // TODO(jmesserly): not sure what kind of boolean conversion rules to
+  // apply for template data-binding. HTML attributes are true if they're
+  // present. However Dart only treats "true" as true. Since this is HTML we'll
+  // use something closer to the HTML rules: null (missing) and false are false,
+  // everything else is true. See: https://github.com/polymer-project/mdv/issues/59
+  static bool _toBoolean(value) => null != value && false != value;
 
-void _addAttributeBindings(Element element, model, syntax) {
-  element.attributes.forEach((name, value) {
-    if (value == '' && (name == 'bind' || name == 'repeat')) {
-      value = '{{}}';
-    }
-    _parseAndBind(element, name, value, model, syntax);
-  });
-}
-
-void _parseAndBind(Node node, String name, String text, model,
-    CustomBindingSyntax syntax) {
-
-  var tokens = _parseMustacheTokens(text);
-  if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
-    return;
-  }
-
-  if (tokens.length == 1 && tokens[0].isBinding) {
-    _bindOrDelegate(node, name, model, tokens[0].value, syntax);
-    return;
-  }
-
-  var replacementBinding = new CompoundBinding();
-  for (var i = 0; i < tokens.length; i++) {
-    var token = tokens[i];
-    if (token.isBinding) {
-      _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
-    }
-  }
-
-  replacementBinding.combinator = (values) {
-    var newValue = new StringBuffer();
-
-    for (var i = 0; i < tokens.length; i++) {
-      var token = tokens[i];
-      if (token.isText) {
-        newValue.write(token.value);
-      } else {
-        var value = values[i];
-        if (value != null) {
-          newValue.write(value);
-        }
+  static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
+    var clone = node.clone(false); // Shallow clone.
+    if (clone is Element && clone.isTemplate) {
+      TemplateElement.decorate(clone, node);
+      if (syntax != null) {
+        clone.attributes.putIfAbsent('syntax', () => syntax);
       }
     }
 
-    return newValue.toString();
-  };
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
+    }
+    return clone;
+  }
 
-  node.bind(name, replacementBinding, 'value');
-}
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  static Document _getTemplateContentsOwner(Document doc) {
+    if (doc.window == null) {
+      return doc;
+    }
+    var d = doc._templateContentsOwner;
+    if (d == null) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHtmlDocument('');
+      while (d.$dom_lastChild != null) {
+        d.$dom_lastChild.remove();
+      }
+      doc._templateContentsOwner = d;
+    }
+    return d;
+  }
 
-void _bindOrDelegate(node, name, model, String path,
-    CustomBindingSyntax syntax) {
+  static Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
+    var clone = templateElement.clone(false);
+    var attributes = templateElement.attributes;
+    for (var name in attributes.keys.toList()) {
+      switch (name) {
+        case 'template':
+        case 'repeat':
+        case 'bind':
+        case 'ref':
+          clone.attributes.remove(name);
+          break;
+        default:
+          attributes.remove(name);
+          break;
+      }
+    }
 
-  if (syntax != null) {
-    var delegateBinding = syntax.getBinding(model, path, name, node);
-    if (delegateBinding != null) {
-      model = delegateBinding;
-      path = 'value';
+    return clone;
+  }
+
+  static void _liftNonNativeChildrenIntoContent(Element templateElement) {
+    var content = templateElement.content;
+
+    if (!templateElement._isAttributeTemplate) {
+      var child;
+      while ((child = templateElement.$dom_firstChild) != null) {
+        content.append(child);
+      }
+      return;
+    }
+
+    // For attribute templates we copy the whole thing into the content and
+    // we move the non template attributes into the content.
+    //
+    //   <tr foo template>
+    //
+    // becomes
+    //
+    //   <tr template>
+    //   + #document-fragment
+    //     + <tr foo>
+    //
+    var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
+    var child;
+    while ((child = templateElement.$dom_firstChild) != null) {
+      newRoot.append(child);
+    }
+    content.append(newRoot);
+  }
+
+  static void _bootstrapTemplatesRecursivelyFrom(Node node) {
+    void bootstrap(template) {
+      if (!TemplateElement.decorate(template)) {
+        _bootstrapTemplatesRecursivelyFrom(template.content);
+      }
+    }
+
+    // Need to do this first as the contents may get lifted if |node| is
+    // template.
+    // TODO(jmesserly): node is DocumentFragment or Element
+    var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
+    if (node is Element && node.isTemplate) bootstrap(node);
+
+    descendents.forEach(bootstrap);
+  }
+
+  static final String _allTemplatesSelectors = 'template, option[template], ' +
+      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
+
+  static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
+    if (node is Element) {
+      _addAttributeBindings(node, model, syntax);
+    } else if (node is Text) {
+      _parseAndBind(node, 'text', node.text, model, syntax);
+    }
+
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      _addBindings(c, model, syntax);
     }
   }
 
-  node.bind(name, model, path);
+  static void _addAttributeBindings(Element element, model, syntax) {
+    element.attributes.forEach((name, value) {
+      if (value == '' && (name == 'bind' || name == 'repeat')) {
+        value = '{{}}';
+      }
+      _parseAndBind(element, name, value, model, syntax);
+    });
+  }
+
+  static void _parseAndBind(Node node, String name, String text, model,
+      CustomBindingSyntax syntax) {
+
+    var tokens = _parseMustacheTokens(text);
+    if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
+      return;
+    }
+
+    // If this is a custom element, give the .xtag a change to bind.
+    node = _nodeOrCustom(node);
+
+    if (tokens.length == 1 && tokens[0].isBinding) {
+      _bindOrDelegate(node, name, model, tokens[0].value, syntax);
+      return;
+    }
+
+    var replacementBinding = new CompoundBinding();
+    for (var i = 0; i < tokens.length; i++) {
+      var token = tokens[i];
+      if (token.isBinding) {
+        _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
+      }
+    }
+
+    replacementBinding.combinator = (values) {
+      var newValue = new StringBuffer();
+
+      for (var i = 0; i < tokens.length; i++) {
+        var token = tokens[i];
+        if (token.isText) {
+          newValue.write(token.value);
+        } else {
+          var value = values[i];
+          if (value != null) {
+            newValue.write(value);
+          }
+        }
+      }
+
+      return newValue.toString();
+    };
+
+    node.bind(name, replacementBinding, 'value');
+  }
+
+  static void _bindOrDelegate(node, name, model, String path,
+      CustomBindingSyntax syntax) {
+
+    if (syntax != null) {
+      var delegateBinding = syntax.getBinding(model, path, name, node);
+      if (delegateBinding != null) {
+        model = delegateBinding;
+        path = 'value';
+      }
+    }
+
+    node.bind(name, model, path);
+  }
+
+  /**
+   * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
+   * the node. This is used so nodes can override [Node.bind], [Node.unbind],
+   * and [Node.unbindAll] like InputElement does.
+   */
+  // TODO(jmesserly): remove this when we can extend Element for real.
+  static _nodeOrCustom(node) => node is Element ? node.xtag : node;
+
+  static List<_BindingToken> _parseMustacheTokens(String s) {
+    var result = [];
+    var length = s.length;
+    var index = 0, lastIndex = 0;
+    while (lastIndex < length) {
+      index = s.indexOf('{{', lastIndex);
+      if (index < 0) {
+        result.add(new _BindingToken(s.substring(lastIndex)));
+        break;
+      } else {
+        // There is a non-empty text run before the next path token.
+        if (index > 0 && lastIndex < index) {
+          result.add(new _BindingToken(s.substring(lastIndex, index)));
+        }
+        lastIndex = index + 2;
+        index = s.indexOf('}}', lastIndex);
+        if (index < 0) {
+          var text = s.substring(lastIndex - 2);
+          if (result.length > 0 && result.last.isText) {
+            result.last.value += text;
+          } else {
+            result.add(new _BindingToken(text));
+          }
+          break;
+        }
+
+        var value = s.substring(lastIndex, index).trim();
+        result.add(new _BindingToken(value, isBinding: true));
+        lastIndex = index + 2;
+      }
+    }
+    return result;
+  }
+
+  static void _addTemplateInstanceRecord(fragment, model) {
+    if (fragment.$dom_firstChild == null) {
+      return;
+    }
+
+    var instanceRecord = new TemplateInstance(
+        fragment.$dom_firstChild, fragment.$dom_lastChild, model);
+
+    var node = instanceRecord.firstNode;
+    while (node != null) {
+      node._templateInstance = instanceRecord;
+      node = node.nextNode;
+    }
+  }
+
+  static void _removeAllBindingsRecursively(Node node) {
+    _nodeOrCustom(node).unbindAll();
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      _removeAllBindingsRecursively(c);
+    }
+  }
+
+  static void _removeChild(Node parent, Node child) {
+    child._templateInstance = null;
+    if (child is Element && child.isTemplate) {
+      // Make sure we stop observing when we remove an element.
+      var templateIterator = child._templateIterator;
+      if (templateIterator != null) {
+        templateIterator.abandon();
+        child._templateIterator = null;
+      }
+    }
+    child.remove();
+    _removeAllBindingsRecursively(child);
+  }
 }
 
 class _BindingToken {
@@ -25479,77 +26624,6 @@
   bool get isText => !isBinding;
 }
 
-List<_BindingToken> _parseMustacheTokens(String s) {
-  var result = [];
-  var length = s.length;
-  var index = 0, lastIndex = 0;
-  while (lastIndex < length) {
-    index = s.indexOf('{{', lastIndex);
-    if (index < 0) {
-      result.add(new _BindingToken(s.substring(lastIndex)));
-      break;
-    } else {
-      // There is a non-empty text run before the next path token.
-      if (index > 0 && lastIndex < index) {
-        result.add(new _BindingToken(s.substring(lastIndex, index)));
-      }
-      lastIndex = index + 2;
-      index = s.indexOf('}}', lastIndex);
-      if (index < 0) {
-        var text = s.substring(lastIndex - 2);
-        if (result.length > 0 && result.last.isText) {
-          result.last.value += text;
-        } else {
-          result.add(new _BindingToken(text));
-        }
-        break;
-      }
-
-      var value = s.substring(lastIndex, index).trim();
-      result.add(new _BindingToken(value, isBinding: true));
-      lastIndex = index + 2;
-    }
-  }
-  return result;
-}
-
-void _addTemplateInstanceRecord(fragment, model) {
-  if (fragment.$dom_firstChild == null) {
-    return;
-  }
-
-  var instanceRecord = new TemplateInstance(
-      fragment.$dom_firstChild, fragment.$dom_lastChild, model);
-
-  var node = instanceRecord.firstNode;
-  while (node != null) {
-    node._templateInstance = instanceRecord;
-    node = node.nextNode;
-  }
-}
-
-void _removeAllBindingsRecursively(Node node) {
-  node.unbindAll();
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    _removeAllBindingsRecursively(c);
-  }
-}
-
-void _removeTemplateChild(Node parent, Node child) {
-  child._templateInstance = null;
-  if (child is Element && child.isTemplate) {
-    // Make sure we stop observing when we remove an element.
-    var templateIterator = child._templateIterator;
-    if (templateIterator != null) {
-      templateIterator.abandon();
-      child._templateIterator = null;
-    }
-  }
-  child.remove();
-  _removeAllBindingsRecursively(child);
-}
-
-
 class _TemplateIterator {
   final Element _templateElement;
   final List<Node> terminators = [];
@@ -25566,7 +26640,7 @@
   }
 
   static Object resolveInputs(Map values) {
-    if (values.containsKey('if') && !_templateBooleanConversion(values['if'])) {
+    if (values.containsKey('if') && !_Bindings._toBoolean(values['if'])) {
       return null;
     }
 
@@ -25627,7 +26701,7 @@
     while (terminator != previousTerminator) {
       var node = terminator;
       terminator = node.previousNode;
-      _removeTemplateChild(parent, node);
+      _Bindings._removeChild(parent, node);
     }
   }
 
@@ -25642,7 +26716,7 @@
     while (terminator != previousTerminator) {
       var node = terminator;
       terminator = node.previousNode;
-      _removeTemplateChild(parent, node);
+      _Bindings._removeChild(parent, node);
     }
   }
 
@@ -25684,8 +26758,8 @@
 
         var fragment = getInstanceFragment(syntax);
 
-        _addBindings(fragment, model, syntax);
-        _addTemplateInstanceRecord(fragment, model);
+        _Bindings._addBindings(fragment, model, syntax);
+        _Bindings._addTemplateInstanceRecord(fragment, model);
 
         insertInstanceAt(addIndex, fragment);
       }
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 3c83672..d9f4473 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -330,16 +330,28 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('DOMApplicationCache.CHECKING')
+  @DocsEditable
   static const int CHECKING = 2;
 
+  @DomName('DOMApplicationCache.DOWNLOADING')
+  @DocsEditable
   static const int DOWNLOADING = 3;
 
+  @DomName('DOMApplicationCache.IDLE')
+  @DocsEditable
   static const int IDLE = 1;
 
+  @DomName('DOMApplicationCache.OBSOLETE')
+  @DocsEditable
   static const int OBSOLETE = 5;
 
+  @DomName('DOMApplicationCache.UNCACHED')
+  @DocsEditable
   static const int UNCACHED = 0;
 
+  @DomName('DOMApplicationCache.UPDATEREADY')
+  @DocsEditable
   static const int UPDATEREADY = 4;
 
   @DomName('DOMApplicationCache.status')
@@ -2468,28 +2480,52 @@
 class CssRule extends NativeFieldWrapperClass1 {
   CssRule.internal();
 
+  @DomName('CSSRule.CHARSET_RULE')
+  @DocsEditable
   static const int CHARSET_RULE = 2;
 
+  @DomName('CSSRule.FONT_FACE_RULE')
+  @DocsEditable
   static const int FONT_FACE_RULE = 5;
 
+  @DomName('CSSRule.HOST_RULE')
+  @DocsEditable
   static const int HOST_RULE = 1001;
 
+  @DomName('CSSRule.IMPORT_RULE')
+  @DocsEditable
   static const int IMPORT_RULE = 3;
 
+  @DomName('CSSRule.MEDIA_RULE')
+  @DocsEditable
   static const int MEDIA_RULE = 4;
 
+  @DomName('CSSRule.PAGE_RULE')
+  @DocsEditable
   static const int PAGE_RULE = 6;
 
+  @DomName('CSSRule.STYLE_RULE')
+  @DocsEditable
   static const int STYLE_RULE = 1;
 
+  @DomName('CSSRule.UNKNOWN_RULE')
+  @DocsEditable
   static const int UNKNOWN_RULE = 0;
 
+  @DomName('CSSRule.WEBKIT_FILTER_RULE')
+  @DocsEditable
   static const int WEBKIT_FILTER_RULE = 17;
 
+  @DomName('CSSRule.WEBKIT_KEYFRAMES_RULE')
+  @DocsEditable
   static const int WEBKIT_KEYFRAMES_RULE = 7;
 
+  @DomName('CSSRule.WEBKIT_KEYFRAME_RULE')
+  @DocsEditable
   static const int WEBKIT_KEYFRAME_RULE = 8;
 
+  @DomName('CSSRule.WEBKIT_REGION_RULE')
+  @DocsEditable
   static const int WEBKIT_REGION_RULE = 16;
 
   @DomName('CSSRule.cssText')
@@ -2568,7 +2604,7 @@
 
   @DomName('CSSStyleDeclaration.setProperty')
   @DocsEditable
-  void setProperty(String propertyName, String value, String priority) native "CSSStyleDeclaration_setProperty_Callback";
+  void _setProperty(String propertyName, String value, String priority) native "CSSStyleDeclaration_setProperty_Callback";
 
 
   String getPropertyValue(String propertyName) {
@@ -2581,6 +2617,14 @@
    */
   static bool get supportsTransitions => true;
 
+  @DomName('CSSStyleDeclaration.setProperty')
+  void setProperty(String propertyName, String value, [String priority]) {
+    if (priority == null) {
+      priority = '';
+    }
+    _setProperty(propertyName, value, priority);
+  }
+
   // TODO(jacobr): generate this list of properties using the existing script.
   /** Gets the value of "align-content" */
   String get alignContent =>
@@ -7247,7 +7291,12 @@
   @DocsEditable
   int get length native "DOMStringList_length_Getter";
 
-  String operator[](int index) native "DOMStringList_item_Callback";
+  String operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  String _nativeIndexedGetter(int index) native "DOMStringList_item_Callback";
 
   void operator[]=(int index, String value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -7260,6 +7309,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  String get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  String get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  String get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  String elementAt(int index) => this[index];
   // -- end List<String> mixins.
 
   @DomName('DOMStringList.contains')
@@ -7750,17 +7824,28 @@
   void onCreated() {}
 
   // Hooks to support custom WebComponents.
+
+  Element _xtag;
+
   /**
    * Experimental support for [web components][wc]. This field stores a
    * reference to the component implementation. It was inspired by Mozilla's
    * [x-tags][] project. Please note: in the future it may be possible to
    * `extend Element` from your class, in which case this field will be
-   * deprecated and will simply return this [Element] object.
+   * deprecated.
+   *
+   * If xtag has not been set, it will simply return `this` [Element].
    *
    * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html
    * [x-tags]: http://x-tags.org/
    */
-  var xtag;
+  // Note: return type is `dynamic` for convenience to suppress warnings when
+  // members of the component are used. The actual type is a subtype of Element.
+  get xtag => _xtag != null ? _xtag : this;
+
+  void set xtag(Element value) {
+    _xtag = value;
+  }
 
   /**
    * Scrolls this element into view.
@@ -7834,24 +7919,24 @@
       self._attributeBindings = new Map<String, StreamSubscription>();
     }
 
-    self.attributes.remove(name);
+    self.xtag.attributes.remove(name);
 
     var changed;
     if (name.endsWith('?')) {
       name = name.substring(0, name.length - 1);
 
       changed = (value) {
-        if (_templateBooleanConversion(value)) {
-          self.attributes[name] = '';
+        if (_Bindings._toBoolean(value)) {
+          self.xtag.attributes[name] = '';
         } else {
-          self.attributes.remove(name);
+          self.xtag.attributes.remove(name);
         }
       };
     } else {
       changed = (value) {
         // TODO(jmesserly): escape value if needed to protect against XSS.
-        // See https://github.com/toolkitchen/mdv/issues/58
-        self.attributes[name] = value == null ? '' : '$value';
+        // See https://github.com/polymer-project/mdv/issues/58
+        self.xtag.attributes[name] = value == null ? '' : '$value';
       };
     }
 
@@ -7974,8 +8059,8 @@
     var template = ref;
     if (template == null) template = this;
 
-    var instance = _createDeepCloneAndDecorateTemplates(template.content,
-        attributes['syntax']);
+    var instance = _Bindings._createDeepCloneAndDecorateTemplates(
+        template.content, attributes['syntax']);
 
     if (TemplateElement._instanceCreated != null) {
       TemplateElement._instanceCreated.add(instance);
@@ -8001,7 +8086,7 @@
 
     var syntax = TemplateElement.syntax[attributes['syntax']];
     _model = value;
-    _addBindings(this, model, syntax);
+    _Bindings._addBindings(this, model, syntax);
   }
 
   // TODO(jmesserly): const set would be better
@@ -8284,6 +8369,8 @@
 
   void insertAdjacentText(String where, String text);
 
+  @DomName('Element.ALLOW_KEYBOARD_INPUT')
+  @DocsEditable
   static const int ALLOW_KEYBOARD_INPUT = 1;
 
   @DomName('Element.attributes')
@@ -9218,44 +9305,84 @@
   }
   Event.internal();
 
+  @DomName('Event.AT_TARGET')
+  @DocsEditable
   static const int AT_TARGET = 2;
 
+  @DomName('Event.BLUR')
+  @DocsEditable
   static const int BLUR = 8192;
 
+  @DomName('Event.BUBBLING_PHASE')
+  @DocsEditable
   static const int BUBBLING_PHASE = 3;
 
+  @DomName('Event.CAPTURING_PHASE')
+  @DocsEditable
   static const int CAPTURING_PHASE = 1;
 
+  @DomName('Event.CHANGE')
+  @DocsEditable
   static const int CHANGE = 32768;
 
+  @DomName('Event.CLICK')
+  @DocsEditable
   static const int CLICK = 64;
 
+  @DomName('Event.DBLCLICK')
+  @DocsEditable
   static const int DBLCLICK = 128;
 
+  @DomName('Event.DRAGDROP')
+  @DocsEditable
   static const int DRAGDROP = 2048;
 
+  @DomName('Event.FOCUS')
+  @DocsEditable
   static const int FOCUS = 4096;
 
+  @DomName('Event.KEYDOWN')
+  @DocsEditable
   static const int KEYDOWN = 256;
 
+  @DomName('Event.KEYPRESS')
+  @DocsEditable
   static const int KEYPRESS = 1024;
 
+  @DomName('Event.KEYUP')
+  @DocsEditable
   static const int KEYUP = 512;
 
+  @DomName('Event.MOUSEDOWN')
+  @DocsEditable
   static const int MOUSEDOWN = 1;
 
+  @DomName('Event.MOUSEDRAG')
+  @DocsEditable
   static const int MOUSEDRAG = 32;
 
+  @DomName('Event.MOUSEMOVE')
+  @DocsEditable
   static const int MOUSEMOVE = 16;
 
+  @DomName('Event.MOUSEOUT')
+  @DocsEditable
   static const int MOUSEOUT = 8;
 
+  @DomName('Event.MOUSEOVER')
+  @DocsEditable
   static const int MOUSEOVER = 4;
 
+  @DomName('Event.MOUSEUP')
+  @DocsEditable
   static const int MOUSEUP = 2;
 
+  @DomName('Event.NONE')
+  @DocsEditable
   static const int NONE = 0;
 
+  @DomName('Event.SELECT')
+  @DocsEditable
   static const int SELECT = 16384;
 
   @DomName('Event.bubbles')
@@ -9334,8 +9461,12 @@
 class EventException extends NativeFieldWrapperClass1 {
   EventException.internal();
 
+  @DomName('EventException.DISPATCH_REQUEST_ERR')
+  @DocsEditable
   static const int DISPATCH_REQUEST_ERR = 1;
 
+  @DomName('EventException.UNSPECIFIED_EVENT_TYPE_ERR')
+  @DocsEditable
   static const int UNSPECIFIED_EVENT_TYPE_ERR = 0;
 
   @DomName('EventException.code')
@@ -9391,10 +9522,16 @@
   @DocsEditable
   static EventSource _create_1(url, eventSourceInit) native "EventSource__create_1constructorCallback";
 
+  @DomName('EventSource.CLOSED')
+  @DocsEditable
   static const int CLOSED = 2;
 
+  @DomName('EventSource.CONNECTING')
+  @DocsEditable
   static const int CONNECTING = 0;
 
+  @DomName('EventSource.OPEN')
+  @DocsEditable
   static const int OPEN = 1;
 
   @DomName('EventSource.readyState')
@@ -9670,28 +9807,52 @@
 class FileError extends NativeFieldWrapperClass1 {
   FileError.internal();
 
+  @DomName('FileError.ABORT_ERR')
+  @DocsEditable
   static const int ABORT_ERR = 3;
 
+  @DomName('FileError.ENCODING_ERR')
+  @DocsEditable
   static const int ENCODING_ERR = 5;
 
+  @DomName('FileError.INVALID_MODIFICATION_ERR')
+  @DocsEditable
   static const int INVALID_MODIFICATION_ERR = 9;
 
+  @DomName('FileError.INVALID_STATE_ERR')
+  @DocsEditable
   static const int INVALID_STATE_ERR = 7;
 
+  @DomName('FileError.NOT_FOUND_ERR')
+  @DocsEditable
   static const int NOT_FOUND_ERR = 1;
 
+  @DomName('FileError.NOT_READABLE_ERR')
+  @DocsEditable
   static const int NOT_READABLE_ERR = 4;
 
+  @DomName('FileError.NO_MODIFICATION_ALLOWED_ERR')
+  @DocsEditable
   static const int NO_MODIFICATION_ALLOWED_ERR = 6;
 
+  @DomName('FileError.PATH_EXISTS_ERR')
+  @DocsEditable
   static const int PATH_EXISTS_ERR = 12;
 
+  @DomName('FileError.QUOTA_EXCEEDED_ERR')
+  @DocsEditable
   static const int QUOTA_EXCEEDED_ERR = 10;
 
+  @DomName('FileError.SECURITY_ERR')
+  @DocsEditable
   static const int SECURITY_ERR = 2;
 
+  @DomName('FileError.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 8;
 
+  @DomName('FileError.TYPE_MISMATCH_ERR')
+  @DocsEditable
   static const int TYPE_MISMATCH_ERR = 11;
 
   @DomName('FileError.code')
@@ -9711,28 +9872,52 @@
 class FileException extends NativeFieldWrapperClass1 {
   FileException.internal();
 
+  @DomName('FileException.ABORT_ERR')
+  @DocsEditable
   static const int ABORT_ERR = 3;
 
+  @DomName('FileException.ENCODING_ERR')
+  @DocsEditable
   static const int ENCODING_ERR = 5;
 
+  @DomName('FileException.INVALID_MODIFICATION_ERR')
+  @DocsEditable
   static const int INVALID_MODIFICATION_ERR = 9;
 
+  @DomName('FileException.INVALID_STATE_ERR')
+  @DocsEditable
   static const int INVALID_STATE_ERR = 7;
 
+  @DomName('FileException.NOT_FOUND_ERR')
+  @DocsEditable
   static const int NOT_FOUND_ERR = 1;
 
+  @DomName('FileException.NOT_READABLE_ERR')
+  @DocsEditable
   static const int NOT_READABLE_ERR = 4;
 
+  @DomName('FileException.NO_MODIFICATION_ALLOWED_ERR')
+  @DocsEditable
   static const int NO_MODIFICATION_ALLOWED_ERR = 6;
 
+  @DomName('FileException.PATH_EXISTS_ERR')
+  @DocsEditable
   static const int PATH_EXISTS_ERR = 12;
 
+  @DomName('FileException.QUOTA_EXCEEDED_ERR')
+  @DocsEditable
   static const int QUOTA_EXCEEDED_ERR = 10;
 
+  @DomName('FileException.SECURITY_ERR')
+  @DocsEditable
   static const int SECURITY_ERR = 2;
 
+  @DomName('FileException.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 8;
 
+  @DomName('FileException.TYPE_MISMATCH_ERR')
+  @DocsEditable
   static const int TYPE_MISMATCH_ERR = 11;
 
   @DomName('FileException.code')
@@ -9768,7 +9953,12 @@
   @DocsEditable
   int get length native "FileList_length_Getter";
 
-  File operator[](int index) native "FileList_item_Callback";
+  File operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  File _nativeIndexedGetter(int index) native "FileList_item_Callback";
 
   void operator[]=(int index, File value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -9781,6 +9971,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  File get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  File get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  File get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  File elementAt(int index) => this[index];
   // -- end List<File> mixins.
 
   @DomName('FileList.item')
@@ -9833,10 +10048,16 @@
   @DocsEditable
   static FileReader _create_1() native "FileReader__create_1constructorCallback";
 
+  @DomName('FileReader.DONE')
+  @DocsEditable
   static const int DONE = 2;
 
+  @DomName('FileReader.EMPTY')
+  @DocsEditable
   static const int EMPTY = 0;
 
+  @DomName('FileReader.LOADING')
+  @DocsEditable
   static const int LOADING = 1;
 
   @DomName('FileReader.error')
@@ -9987,10 +10208,16 @@
   @DocsEditable
   static const EventStreamProvider<ProgressEvent> writeStartEvent = const EventStreamProvider<ProgressEvent>('writestart');
 
+  @DomName('FileWriter.DONE')
+  @DocsEditable
   static const int DONE = 2;
 
+  @DomName('FileWriter.INIT')
+  @DocsEditable
   static const int INIT = 0;
 
+  @DomName('FileWriter.WRITING')
+  @DocsEditable
   static const int WRITING = 1;
 
   @DomName('FileWriter.error')
@@ -10614,7 +10841,12 @@
   @DocsEditable
   int get length native "HTMLAllCollection_length_Getter";
 
-  Node operator[](int index) native "HTMLAllCollection_item_Callback";
+  Node operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Node _nativeIndexedGetter(int index) native "HTMLAllCollection_item_Callback";
 
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -10627,6 +10859,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @DomName('HTMLAllCollection.item')
@@ -10658,7 +10915,12 @@
   @DocsEditable
   int get length native "HTMLCollection_length_Getter";
 
-  Node operator[](int index) native "HTMLCollection_item_Callback";
+  Node operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Node _nativeIndexedGetter(int index) native "HTMLCollection_item_Callback";
 
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -10671,6 +10933,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @DomName('HTMLCollection.item')
@@ -10984,7 +11271,8 @@
    * See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access_authentication).
    */
   static Future<HttpRequest> request(String url,
-      {String method, bool withCredentials, String responseType, sendData,
+      {String method, bool withCredentials, String responseType,
+      String mimeType, Map<String, String> requestHeaders, sendData,
       void onProgress(ProgressEvent e)}) {
     var completer = new Completer<HttpRequest>();
 
@@ -11002,6 +11290,16 @@
       xhr.responseType = responseType;
     }
 
+    if (mimeType != null) {
+      xhr.overrideMimeType(mimeType);
+    }
+
+    if (requestHeaders != null) {
+      requestHeaders.forEach((header, value) {
+        xhr.setRequestHeader(header, value);
+      });
+    }
+
     if (onProgress != null) {
       xhr.onProgress.listen(onProgress);
     }
@@ -11054,6 +11352,14 @@
     return true;
   }
 
+  /**
+   * Checks to see if the overrideMimeType method is supported on the current
+   * platform.
+   */
+  static bool get supportsOverrideMimeType {
+    return true;
+  }
+
   HttpRequest.internal() : super.internal();
 
   @DomName('XMLHttpRequest.abortEvent')
@@ -11088,14 +11394,24 @@
   @DocsEditable
   static HttpRequest _create() native "XMLHttpRequest_constructorCallback";
 
+  @DomName('XMLHttpRequest.DONE')
+  @DocsEditable
   static const int DONE = 4;
 
+  @DomName('XMLHttpRequest.HEADERS_RECEIVED')
+  @DocsEditable
   static const int HEADERS_RECEIVED = 2;
 
+  @DomName('XMLHttpRequest.LOADING')
+  @DocsEditable
   static const int LOADING = 3;
 
+  @DomName('XMLHttpRequest.OPENED')
+  @DocsEditable
   static const int OPENED = 1;
 
+  @DomName('XMLHttpRequest.UNSENT')
+  @DocsEditable
   static const int UNSENT = 0;
 
   /**
@@ -11305,6 +11621,9 @@
    */
   @DomName('XMLHttpRequest.overrideMimeType')
   @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
   void overrideMimeType(String override) native "XMLHttpRequest_overrideMimeType_Callback";
 
   @DomName('XMLHttpRequest.removeEventListener')
@@ -11407,8 +11726,12 @@
 class HttpRequestException extends NativeFieldWrapperClass1 {
   HttpRequestException.internal();
 
+  @DomName('XMLHttpRequestException.ABORT_ERR')
+  @DocsEditable
   static const int ABORT_ERR = 102;
 
+  @DomName('XMLHttpRequestException.NETWORK_ERR')
+  @DocsEditable
   static const int NETWORK_ERR = 101;
 
   @DomName('XMLHttpRequestException.code')
@@ -13562,22 +13885,40 @@
   @Experimental
   static const EventStreamProvider<MediaKeyEvent> needKeyEvent = const EventStreamProvider<MediaKeyEvent>('webkitneedkey');
 
+  @DomName('HTMLMediaElement.HAVE_CURRENT_DATA')
+  @DocsEditable
   static const int HAVE_CURRENT_DATA = 2;
 
+  @DomName('HTMLMediaElement.HAVE_ENOUGH_DATA')
+  @DocsEditable
   static const int HAVE_ENOUGH_DATA = 4;
 
+  @DomName('HTMLMediaElement.HAVE_FUTURE_DATA')
+  @DocsEditable
   static const int HAVE_FUTURE_DATA = 3;
 
+  @DomName('HTMLMediaElement.HAVE_METADATA')
+  @DocsEditable
   static const int HAVE_METADATA = 1;
 
+  @DomName('HTMLMediaElement.HAVE_NOTHING')
+  @DocsEditable
   static const int HAVE_NOTHING = 0;
 
+  @DomName('HTMLMediaElement.NETWORK_EMPTY')
+  @DocsEditable
   static const int NETWORK_EMPTY = 0;
 
+  @DomName('HTMLMediaElement.NETWORK_IDLE')
+  @DocsEditable
   static const int NETWORK_IDLE = 1;
 
+  @DomName('HTMLMediaElement.NETWORK_LOADING')
+  @DocsEditable
   static const int NETWORK_LOADING = 2;
 
+  @DomName('HTMLMediaElement.NETWORK_NO_SOURCE')
+  @DocsEditable
   static const int NETWORK_NO_SOURCE = 3;
 
   @DomName('HTMLMediaElement.autoplay')
@@ -13967,14 +14308,24 @@
 class MediaError extends NativeFieldWrapperClass1 {
   MediaError.internal();
 
+  @DomName('MediaError.MEDIA_ERR_ABORTED')
+  @DocsEditable
   static const int MEDIA_ERR_ABORTED = 1;
 
+  @DomName('MediaError.MEDIA_ERR_DECODE')
+  @DocsEditable
   static const int MEDIA_ERR_DECODE = 3;
 
+  @DomName('MediaError.MEDIA_ERR_ENCRYPTED')
+  @DocsEditable
   static const int MEDIA_ERR_ENCRYPTED = 5;
 
+  @DomName('MediaError.MEDIA_ERR_NETWORK')
+  @DocsEditable
   static const int MEDIA_ERR_NETWORK = 2;
 
+  @DomName('MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED')
+  @DocsEditable
   static const int MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
 
   @DomName('MediaError.code')
@@ -13994,16 +14345,28 @@
 class MediaKeyError extends NativeFieldWrapperClass1 {
   MediaKeyError.internal();
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_CLIENT')
+  @DocsEditable
   static const int MEDIA_KEYERR_CLIENT = 2;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_DOMAIN')
+  @DocsEditable
   static const int MEDIA_KEYERR_DOMAIN = 6;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_HARDWARECHANGE')
+  @DocsEditable
   static const int MEDIA_KEYERR_HARDWARECHANGE = 5;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_OUTPUT')
+  @DocsEditable
   static const int MEDIA_KEYERR_OUTPUT = 4;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_SERVICE')
+  @DocsEditable
   static const int MEDIA_KEYERR_SERVICE = 3;
 
+  @DomName('MediaKeyError.MEDIA_KEYERR_UNKNOWN')
+  @DocsEditable
   static const int MEDIA_KEYERR_UNKNOWN = 1;
 
   @DomName('MediaKeyError.code')
@@ -14793,7 +15156,12 @@
   @DocsEditable
   int get length native "DOMMimeTypeArray_length_Getter";
 
-  MimeType operator[](int index) native "DOMMimeTypeArray_item_Callback";
+  MimeType operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  MimeType _nativeIndexedGetter(int index) native "DOMMimeTypeArray_item_Callback";
 
   void operator[]=(int index, MimeType value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -14806,6 +15174,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  MimeType get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  MimeType get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  MimeType get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  MimeType elementAt(int index) => this[index];
   // -- end List<MimeType> mixins.
 
   @DomName('MimeTypeArray.item')
@@ -15018,10 +15411,16 @@
   }
   MutationEvent.internal() : super.internal();
 
+  @DomName('MutationEvent.ADDITION')
+  @DocsEditable
   static const int ADDITION = 2;
 
+  @DomName('MutationEvent.MODIFICATION')
+  @DocsEditable
   static const int MODIFICATION = 1;
 
+  @DomName('MutationEvent.REMOVAL')
+  @DocsEditable
   static const int REMOVAL = 3;
 
   @DomName('MutationEvent.attrChange')
@@ -15446,6 +15845,8 @@
 class NavigatorUserMediaError extends NativeFieldWrapperClass1 {
   NavigatorUserMediaError.internal();
 
+  @DomName('NavigatorUserMediaError.PERMISSION_DENIED')
+  @DocsEditable
   static const int PERMISSION_DENIED = 1;
 
   @DomName('NavigatorUserMediaError.code')
@@ -15732,28 +16133,52 @@
 
   Node.internal() : super.internal();
 
+  @DomName('Node.ATTRIBUTE_NODE')
+  @DocsEditable
   static const int ATTRIBUTE_NODE = 2;
 
+  @DomName('Node.CDATA_SECTION_NODE')
+  @DocsEditable
   static const int CDATA_SECTION_NODE = 4;
 
+  @DomName('Node.COMMENT_NODE')
+  @DocsEditable
   static const int COMMENT_NODE = 8;
 
+  @DomName('Node.DOCUMENT_FRAGMENT_NODE')
+  @DocsEditable
   static const int DOCUMENT_FRAGMENT_NODE = 11;
 
+  @DomName('Node.DOCUMENT_NODE')
+  @DocsEditable
   static const int DOCUMENT_NODE = 9;
 
+  @DomName('Node.DOCUMENT_TYPE_NODE')
+  @DocsEditable
   static const int DOCUMENT_TYPE_NODE = 10;
 
+  @DomName('Node.ELEMENT_NODE')
+  @DocsEditable
   static const int ELEMENT_NODE = 1;
 
+  @DomName('Node.ENTITY_NODE')
+  @DocsEditable
   static const int ENTITY_NODE = 6;
 
+  @DomName('Node.ENTITY_REFERENCE_NODE')
+  @DocsEditable
   static const int ENTITY_REFERENCE_NODE = 5;
 
+  @DomName('Node.NOTATION_NODE')
+  @DocsEditable
   static const int NOTATION_NODE = 12;
 
+  @DomName('Node.PROCESSING_INSTRUCTION_NODE')
+  @DocsEditable
   static const int PROCESSING_INSTRUCTION_NODE = 7;
 
+  @DomName('Node.TEXT_NODE')
+  @DocsEditable
   static const int TEXT_NODE = 3;
 
   @DomName('Node.childNodes')
@@ -15816,6 +16241,15 @@
   @DocsEditable
   void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "Node_addEventListener_Callback";
 
+  /**
+   * Adds a node to the end of the child [nodes] list of this node.
+   *
+   * If the node already exists in this document, it will be removed from its
+   * current parent node, then added to this node.
+   *
+   * This method is more efficient than `nodes.add`, and is the preferred
+   * way of appending a child node.
+   */
   @DomName('Node.appendChild')
   @DocsEditable
   Node append(Node newChild) native "Node_appendChild_Callback";
@@ -15865,36 +16299,68 @@
 class NodeFilter extends NativeFieldWrapperClass1 {
   NodeFilter.internal();
 
+  @DomName('NodeFilter.FILTER_ACCEPT')
+  @DocsEditable
   static const int FILTER_ACCEPT = 1;
 
+  @DomName('NodeFilter.FILTER_REJECT')
+  @DocsEditable
   static const int FILTER_REJECT = 2;
 
+  @DomName('NodeFilter.FILTER_SKIP')
+  @DocsEditable
   static const int FILTER_SKIP = 3;
 
+  @DomName('NodeFilter.SHOW_ALL')
+  @DocsEditable
   static const int SHOW_ALL = 0xFFFFFFFF;
 
+  @DomName('NodeFilter.SHOW_ATTRIBUTE')
+  @DocsEditable
   static const int SHOW_ATTRIBUTE = 0x00000002;
 
+  @DomName('NodeFilter.SHOW_CDATA_SECTION')
+  @DocsEditable
   static const int SHOW_CDATA_SECTION = 0x00000008;
 
+  @DomName('NodeFilter.SHOW_COMMENT')
+  @DocsEditable
   static const int SHOW_COMMENT = 0x00000080;
 
+  @DomName('NodeFilter.SHOW_DOCUMENT')
+  @DocsEditable
   static const int SHOW_DOCUMENT = 0x00000100;
 
+  @DomName('NodeFilter.SHOW_DOCUMENT_FRAGMENT')
+  @DocsEditable
   static const int SHOW_DOCUMENT_FRAGMENT = 0x00000400;
 
+  @DomName('NodeFilter.SHOW_DOCUMENT_TYPE')
+  @DocsEditable
   static const int SHOW_DOCUMENT_TYPE = 0x00000200;
 
+  @DomName('NodeFilter.SHOW_ELEMENT')
+  @DocsEditable
   static const int SHOW_ELEMENT = 0x00000001;
 
+  @DomName('NodeFilter.SHOW_ENTITY')
+  @DocsEditable
   static const int SHOW_ENTITY = 0x00000020;
 
+  @DomName('NodeFilter.SHOW_ENTITY_REFERENCE')
+  @DocsEditable
   static const int SHOW_ENTITY_REFERENCE = 0x00000010;
 
+  @DomName('NodeFilter.SHOW_NOTATION')
+  @DocsEditable
   static const int SHOW_NOTATION = 0x00000800;
 
+  @DomName('NodeFilter.SHOW_PROCESSING_INSTRUCTION')
+  @DocsEditable
   static const int SHOW_PROCESSING_INSTRUCTION = 0x00000040;
 
+  @DomName('NodeFilter.SHOW_TEXT')
+  @DocsEditable
   static const int SHOW_TEXT = 0x00000004;
 
 }
@@ -15955,7 +16421,12 @@
   @DocsEditable
   int get length native "NodeList_length_Getter";
 
-  Node operator[](int index) native "NodeList_item_Callback";
+  Node operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Node _nativeIndexedGetter(int index) native "NodeList_item_Callback";
 
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -15968,6 +16439,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @DomName('NodeList.item')
@@ -16523,10 +17019,16 @@
 class OverflowEvent extends Event {
   OverflowEvent.internal() : super.internal();
 
+  @DomName('OverflowEvent.BOTH')
+  @DocsEditable
   static const int BOTH = 2;
 
+  @DomName('OverflowEvent.HORIZONTAL')
+  @DocsEditable
   static const int HORIZONTAL = 0;
 
+  @DomName('OverflowEvent.VERTICAL')
+  @DocsEditable
   static const int VERTICAL = 1;
 
   @DomName('OverflowEvent.horizontalOverflow')
@@ -16864,12 +17366,20 @@
 class PerformanceNavigation extends NativeFieldWrapperClass1 {
   PerformanceNavigation.internal();
 
+  @DomName('PerformanceNavigation.TYPE_BACK_FORWARD')
+  @DocsEditable
   static const int TYPE_BACK_FORWARD = 2;
 
+  @DomName('PerformanceNavigation.TYPE_NAVIGATE')
+  @DocsEditable
   static const int TYPE_NAVIGATE = 0;
 
+  @DomName('PerformanceNavigation.TYPE_RELOAD')
+  @DocsEditable
   static const int TYPE_RELOAD = 1;
 
+  @DomName('PerformanceNavigation.TYPE_RESERVED')
+  @DocsEditable
   static const int TYPE_RESERVED = 255;
 
   @DomName('PerformanceNavigation.redirectCount')
@@ -17092,7 +17602,12 @@
   @DocsEditable
   int get length native "DOMPluginArray_length_Getter";
 
-  Plugin operator[](int index) native "DOMPluginArray_item_Callback";
+  Plugin operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Plugin _nativeIndexedGetter(int index) native "DOMPluginArray_item_Callback";
 
   void operator[]=(int index, Plugin value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -17105,6 +17620,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Plugin get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Plugin get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Plugin get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Plugin elementAt(int index) => this[index];
   // -- end List<Plugin> mixins.
 
   @DomName('PluginArray.item')
@@ -17161,10 +17701,16 @@
 class PositionError extends NativeFieldWrapperClass1 {
   PositionError.internal();
 
+  @DomName('PositionError.PERMISSION_DENIED')
+  @DocsEditable
   static const int PERMISSION_DENIED = 1;
 
+  @DomName('PositionError.POSITION_UNAVAILABLE')
+  @DocsEditable
   static const int POSITION_UNAVAILABLE = 2;
 
+  @DomName('PositionError.TIMEOUT')
+  @DocsEditable
   static const int TIMEOUT = 3;
 
   @DomName('PositionError.code')
@@ -17369,20 +17915,36 @@
 
   Range.internal();
 
+  @DomName('Range.END_TO_END')
+  @DocsEditable
   static const int END_TO_END = 2;
 
+  @DomName('Range.END_TO_START')
+  @DocsEditable
   static const int END_TO_START = 3;
 
+  @DomName('Range.NODE_AFTER')
+  @DocsEditable
   static const int NODE_AFTER = 1;
 
+  @DomName('Range.NODE_BEFORE')
+  @DocsEditable
   static const int NODE_BEFORE = 0;
 
+  @DomName('Range.NODE_BEFORE_AND_AFTER')
+  @DocsEditable
   static const int NODE_BEFORE_AND_AFTER = 2;
 
+  @DomName('Range.NODE_INSIDE')
+  @DocsEditable
   static const int NODE_INSIDE = 3;
 
+  @DomName('Range.START_TO_END')
+  @DocsEditable
   static const int START_TO_END = 1;
 
+  @DomName('Range.START_TO_START')
+  @DocsEditable
   static const int START_TO_START = 0;
 
   @DomName('Range.collapsed')
@@ -17531,8 +18093,12 @@
 class RangeException extends NativeFieldWrapperClass1 {
   RangeException.internal();
 
+  @DomName('RangeException.BAD_BOUNDARYPOINTS_ERR')
+  @DocsEditable
   static const int BAD_BOUNDARYPOINTS_ERR = 1;
 
+  @DomName('RangeException.INVALID_NODE_TYPE_ERR')
+  @DocsEditable
   static const int INVALID_NODE_TYPE_ERR = 2;
 
   @DomName('RangeException.code')
@@ -18882,7 +19448,12 @@
   @DocsEditable
   int get length native "SourceBufferList_length_Getter";
 
-  SourceBuffer operator[](int index) native "SourceBufferList_item_Callback";
+  SourceBuffer operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  SourceBuffer _nativeIndexedGetter(int index) native "SourceBufferList_item_Callback";
 
   void operator[]=(int index, SourceBuffer value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -18895,6 +19466,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SourceBuffer get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  SourceBuffer get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  SourceBuffer get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SourceBuffer elementAt(int index) => this[index];
   // -- end List<SourceBuffer> mixins.
 
   @DomName('SourceBufferList.addEventListener')
@@ -19035,7 +19631,12 @@
   @DocsEditable
   int get length native "SpeechGrammarList_length_Getter";
 
-  SpeechGrammar operator[](int index) native "SpeechGrammarList_item_Callback";
+  SpeechGrammar operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  SpeechGrammar _nativeIndexedGetter(int index) native "SpeechGrammarList_item_Callback";
 
   void operator[]=(int index, SpeechGrammar value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -19048,6 +19649,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SpeechGrammar get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechGrammar get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechGrammar get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SpeechGrammar elementAt(int index) => this[index];
   // -- end List<SpeechGrammar> mixins.
 
   void addFromString(String string, [num weight]) {
@@ -19571,8 +20197,12 @@
 class StorageInfo extends NativeFieldWrapperClass1 {
   StorageInfo.internal();
 
+  @DomName('StorageInfo.PERSISTENT')
+  @DocsEditable
   static const int PERSISTENT = 1;
 
+  @DomName('StorageInfo.TEMPORARY')
+  @DocsEditable
   static const int TEMPORARY = 0;
 
   @DomName('StorageInfo.queryUsageAndQuota')
@@ -20122,7 +20752,7 @@
 
     // Create content
     if (template is! TemplateElement) {
-      var doc = _getTemplateContentsOwner(template.document);
+      var doc = _Bindings._getTemplateContentsOwner(template.document);
       template._templateContent = doc.createDocumentFragment();
     }
 
@@ -20132,9 +20762,9 @@
     }
 
     if (template is TemplateElement) {
-      _bootstrapTemplatesRecursivelyFrom(template.content);
+      bootstrap(template.content);
     } else {
-      _liftNonNativeTemplateChildrenIntoContent(template);
+      _Bindings._liftNonNativeChildrenIntoContent(template);
     }
 
     return true;
@@ -20150,7 +20780,23 @@
   // TODO(rafaelw): Review whether this is the right public API.
   @Experimental
   static void bootstrap(Node content) {
-    _bootstrapTemplatesRecursivelyFrom(content);
+    _Bindings._bootstrapTemplatesRecursivelyFrom(content);
+  }
+
+  /**
+   * Binds all mustaches recursively starting from the [root] node.
+   *
+   * Note: this is not an official Model-Driven-Views API; it is intended to
+   * support binding the [ShadowRoot]'s content to a model.
+   */
+  // TODO(jmesserly): this is needed to avoid two <template> nodes when using
+  // bindings in a custom element's template. See also:
+  // https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
+  // Called from:
+  // https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
+  @Experimental
+  static void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
+    _Bindings._addBindings(root, model, syntax);
   }
 
   static bool _initStyles;
@@ -20742,7 +21388,12 @@
   @DocsEditable
   int get length native "TextTrackCueList_length_Getter";
 
-  TextTrackCue operator[](int index) native "TextTrackCueList_item_Callback";
+  TextTrackCue operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  TextTrackCue _nativeIndexedGetter(int index) native "TextTrackCueList_item_Callback";
 
   void operator[]=(int index, TextTrackCue value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -20755,6 +21406,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  TextTrackCue get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrackCue get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrackCue get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  TextTrackCue elementAt(int index) => this[index];
   // -- end List<TextTrackCue> mixins.
 
   @DomName('TextTrackCueList.getCueById')
@@ -20786,7 +21462,12 @@
   @DocsEditable
   int get length native "TextTrackList_length_Getter";
 
-  TextTrack operator[](int index) native "TextTrackList_item_Callback";
+  TextTrack operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  TextTrack _nativeIndexedGetter(int index) native "TextTrackList_item_Callback";
 
   void operator[]=(int index, TextTrack value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -20799,6 +21480,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  TextTrack get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrack get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  TextTrack get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  TextTrack elementAt(int index) => this[index];
   // -- end List<TextTrack> mixins.
 
   @DomName('TextTrackList.addEventListener')
@@ -21047,7 +21753,12 @@
   @DocsEditable
   int get length native "TouchList_length_Getter";
 
-  Touch operator[](int index) native "TouchList_item_Callback";
+  Touch operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Touch _nativeIndexedGetter(int index) native "TouchList_item_Callback";
 
   void operator[]=(int index, Touch value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -21060,6 +21771,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Touch get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Touch get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Touch get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Touch elementAt(int index) => this[index];
   // -- end List<Touch> mixins.
 
   @DomName('TouchList.item')
@@ -21089,12 +21825,20 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('HTMLTrackElement.ERROR')
+  @DocsEditable
   static const int ERROR = 3;
 
+  @DomName('HTMLTrackElement.LOADED')
+  @DocsEditable
   static const int LOADED = 2;
 
+  @DomName('HTMLTrackElement.LOADING')
+  @DocsEditable
   static const int LOADING = 1;
 
+  @DomName('HTMLTrackElement.NONE')
+  @DocsEditable
   static const int NONE = 0;
 
   @DomName('HTMLTrackElement.default')
@@ -21661,12 +22405,20 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('WebSocket.CLOSED')
+  @DocsEditable
   static const int CLOSED = 3;
 
+  @DomName('WebSocket.CLOSING')
+  @DocsEditable
   static const int CLOSING = 2;
 
+  @DomName('WebSocket.CONNECTING')
+  @DocsEditable
   static const int CONNECTING = 0;
 
+  @DomName('WebSocket.OPEN')
+  @DocsEditable
   static const int OPEN = 1;
 
   @DomName('WebSocket.URL')
@@ -21794,10 +22546,16 @@
 
   WheelEvent.internal() : super.internal();
 
+  @DomName('WheelEvent.DOM_DELTA_LINE')
+  @DocsEditable
   static const int DOM_DELTA_LINE = 0x01;
 
+  @DomName('WheelEvent.DOM_DELTA_PAGE')
+  @DocsEditable
   static const int DOM_DELTA_PAGE = 0x02;
 
+  @DomName('WheelEvent.DOM_DELTA_PIXEL')
+  @DocsEditable
   static const int DOM_DELTA_PIXEL = 0x00;
 
   @DomName('WheelEvent.deltaMode')
@@ -22029,8 +22787,12 @@
   @Experimental
   static const EventStreamProvider<AnimationEvent> animationStartEvent = const EventStreamProvider<AnimationEvent>('webkitAnimationStart');
 
+  @DomName('Window.PERSISTENT')
+  @DocsEditable
   static const int PERSISTENT = 1;
 
+  @DomName('Window.TEMPORARY')
+  @DocsEditable
   static const int TEMPORARY = 0;
 
   @DomName('Window.applicationCache')
@@ -22798,8 +23560,12 @@
 class XPathException extends NativeFieldWrapperClass1 {
   XPathException.internal();
 
+  @DomName('XPathException.INVALID_EXPRESSION_ERR')
+  @DocsEditable
   static const int INVALID_EXPRESSION_ERR = 51;
 
+  @DomName('XPathException.TYPE_ERR')
+  @DocsEditable
   static const int TYPE_ERR = 52;
 
   @DomName('XPathException.code')
@@ -22865,24 +23631,44 @@
 class XPathResult extends NativeFieldWrapperClass1 {
   XPathResult.internal();
 
+  @DomName('XPathResult.ANY_TYPE')
+  @DocsEditable
   static const int ANY_TYPE = 0;
 
+  @DomName('XPathResult.ANY_UNORDERED_NODE_TYPE')
+  @DocsEditable
   static const int ANY_UNORDERED_NODE_TYPE = 8;
 
+  @DomName('XPathResult.BOOLEAN_TYPE')
+  @DocsEditable
   static const int BOOLEAN_TYPE = 3;
 
+  @DomName('XPathResult.FIRST_ORDERED_NODE_TYPE')
+  @DocsEditable
   static const int FIRST_ORDERED_NODE_TYPE = 9;
 
+  @DomName('XPathResult.NUMBER_TYPE')
+  @DocsEditable
   static const int NUMBER_TYPE = 1;
 
+  @DomName('XPathResult.ORDERED_NODE_ITERATOR_TYPE')
+  @DocsEditable
   static const int ORDERED_NODE_ITERATOR_TYPE = 5;
 
+  @DomName('XPathResult.ORDERED_NODE_SNAPSHOT_TYPE')
+  @DocsEditable
   static const int ORDERED_NODE_SNAPSHOT_TYPE = 7;
 
+  @DomName('XPathResult.STRING_TYPE')
+  @DocsEditable
   static const int STRING_TYPE = 2;
 
+  @DomName('XPathResult.UNORDERED_NODE_ITERATOR_TYPE')
+  @DocsEditable
   static const int UNORDERED_NODE_ITERATOR_TYPE = 4;
 
+  @DomName('XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE')
+  @DocsEditable
   static const int UNORDERED_NODE_SNAPSHOT_TYPE = 6;
 
   @DomName('XPathResult.booleanValue')
@@ -23176,7 +23962,12 @@
   @DocsEditable
   int get length native "ClientRectList_length_Getter";
 
-  Rect operator[](int index) native "ClientRectList_item_Callback";
+  Rect operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Rect _nativeIndexedGetter(int index) native "ClientRectList_item_Callback";
 
   void operator[]=(int index, Rect value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23189,6 +23980,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Rect get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Rect get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Rect get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Rect elementAt(int index) => this[index];
   // -- end List<Rect> mixins.
 
   @DomName('ClientRectList.item')
@@ -23225,7 +24041,12 @@
   @DocsEditable
   int get length native "CSSRuleList_length_Getter";
 
-  CssRule operator[](int index) native "CSSRuleList_item_Callback";
+  CssRule operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  CssRule _nativeIndexedGetter(int index) native "CSSRuleList_item_Callback";
 
   void operator[]=(int index, CssRule value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23238,6 +24059,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  CssRule get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  CssRule get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  CssRule get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  CssRule elementAt(int index) => this[index];
   // -- end List<CssRule> mixins.
 
   @DomName('CSSRuleList.item')
@@ -23261,7 +24107,12 @@
   @DocsEditable
   int get length native "CSSValueList_length_Getter";
 
-  _CSSValue operator[](int index) native "CSSValueList_item_Callback";
+  _CSSValue operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  _CSSValue _nativeIndexedGetter(int index) native "CSSValueList_item_Callback";
 
   void operator[]=(int index, _CSSValue value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23274,6 +24125,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  _CSSValue get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  _CSSValue get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  _CSSValue get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  _CSSValue elementAt(int index) => this[index];
   // -- end List<_CSSValue> mixins.
 
   @DomName('CSSValueList.item')
@@ -23562,7 +24438,12 @@
   @DocsEditable
   int get length native "EntryArray_length_Getter";
 
-  Entry operator[](int index) native "EntryArray_item_Callback";
+  Entry operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Entry _nativeIndexedGetter(int index) native "EntryArray_item_Callback";
 
   void operator[]=(int index, Entry value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23575,6 +24456,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Entry get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Entry get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Entry get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Entry elementAt(int index) => this[index];
   // -- end List<Entry> mixins.
 
   @DomName('EntryArray.item')
@@ -23598,7 +24504,12 @@
   @DocsEditable
   int get length native "EntryArraySync_length_Getter";
 
-  _EntrySync operator[](int index) native "EntryArraySync_item_Callback";
+  _EntrySync operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  _EntrySync _nativeIndexedGetter(int index) native "EntryArraySync_item_Callback";
 
   void operator[]=(int index, _EntrySync value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23611,6 +24522,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  _EntrySync get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  _EntrySync get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  _EntrySync get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  _EntrySync elementAt(int index) => this[index];
   // -- end List<_EntrySync> mixins.
 
   @DomName('EntryArraySync.item')
@@ -23695,7 +24631,12 @@
   @DocsEditable
   int get length native "GamepadList_length_Getter";
 
-  Gamepad operator[](int index) native "GamepadList_item_Callback";
+  Gamepad operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Gamepad _nativeIndexedGetter(int index) native "GamepadList_item_Callback";
 
   void operator[]=(int index, Gamepad value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23708,6 +24649,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Gamepad get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Gamepad get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Gamepad get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Gamepad elementAt(int index) => this[index];
   // -- end List<Gamepad> mixins.
 
   @DomName('GamepadList.item')
@@ -23822,7 +24788,12 @@
   @DocsEditable
   int get length native "NamedNodeMap_length_Getter";
 
-  Node operator[](int index) native "NamedNodeMap_item_Callback";
+  Node operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Node _nativeIndexedGetter(int index) native "NamedNodeMap_item_Callback";
 
   void operator[]=(int index, Node value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23835,6 +24806,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Node get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Node get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
   @DomName('NamedNodeMap.getNamedItem')
@@ -23966,7 +24962,12 @@
   @DocsEditable
   int get length native "SpeechInputResultList_length_Getter";
 
-  SpeechInputResult operator[](int index) native "SpeechInputResultList_item_Callback";
+  SpeechInputResult operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  SpeechInputResult _nativeIndexedGetter(int index) native "SpeechInputResultList_item_Callback";
 
   void operator[]=(int index, SpeechInputResult value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -23979,6 +24980,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SpeechInputResult get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechInputResult get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechInputResult get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SpeechInputResult elementAt(int index) => this[index];
   // -- end List<SpeechInputResult> mixins.
 
   @DomName('SpeechInputResultList.item')
@@ -24002,7 +25028,12 @@
   @DocsEditable
   int get length native "SpeechRecognitionResultList_length_Getter";
 
-  SpeechRecognitionResult operator[](int index) native "SpeechRecognitionResultList_item_Callback";
+  SpeechRecognitionResult operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  SpeechRecognitionResult _nativeIndexedGetter(int index) native "SpeechRecognitionResultList_item_Callback";
 
   void operator[]=(int index, SpeechRecognitionResult value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -24015,6 +25046,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  SpeechRecognitionResult get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechRecognitionResult get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  SpeechRecognitionResult get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  SpeechRecognitionResult elementAt(int index) => this[index];
   // -- end List<SpeechRecognitionResult> mixins.
 
   @DomName('SpeechRecognitionResultList.item')
@@ -24038,7 +25094,12 @@
   @DocsEditable
   int get length native "StyleSheetList_length_Getter";
 
-  StyleSheet operator[](int index) native "StyleSheetList_item_Callback";
+  StyleSheet operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  StyleSheet _nativeIndexedGetter(int index) native "StyleSheetList_item_Callback";
 
   void operator[]=(int index, StyleSheet value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -24051,6 +25112,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  StyleSheet get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  StyleSheet get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  StyleSheet get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  StyleSheet elementAt(int index) => this[index];
   // -- end List<StyleSheet> mixins.
 
   @DomName('StyleSheetList.item')
@@ -26628,7 +27714,7 @@
 
 
 // This code is a port of Model-Driven-Views:
-// https://github.com/toolkitchen/mdv
+// https://github.com/polymer-project/mdv
 // The code mostly comes from src/template_element.js
 
 typedef void _ChangeHandler(value);
@@ -26660,7 +27746,7 @@
  *
  *     TemplateElement.syntax['MySyntax'] = new MySyntax();
  *
- * See <https://github.com/toolkitchen/mdv/blob/master/docs/syntax.md> for more
+ * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for more
  * information about Custom Syntax.
  */
 // TODO(jmesserly): if this is just one method, a function type would make it
@@ -26869,19 +27955,6 @@
   }
 }
 
-Stream<Event> _getStreamForInputType(InputElement element) {
-  switch (element.type) {
-    case 'checkbox':
-      return element.onClick;
-    case 'radio':
-    case 'select-multiple':
-    case 'select-one':
-      return element.onChange;
-    default:
-      return element.onInput;
-  }
-}
-
 abstract class _InputBinding {
   final InputElement element;
   PathObserver binding;
@@ -26903,6 +27976,20 @@
     _pathSub.cancel();
     _eventSub.cancel();
   }
+
+
+  static Stream<Event> _getStreamForInputType(InputElement element) {
+    switch (element.type) {
+      case 'checkbox':
+        return element.onClick;
+      case 'radio':
+      case 'select-multiple':
+      case 'select-one':
+        return element.onChange;
+      default:
+        return element.onInput;
+    }
+  }
 }
 
 class _ValueBinding extends _InputBinding {
@@ -26917,18 +28004,11 @@
   }
 }
 
-// TODO(jmesserly): not sure what kind of boolean conversion rules to
-// apply for template data-binding. HTML attributes are true if they're present.
-// However Dart only treats "true" as true. Since this is HTML we'll use
-// something closer to the HTML rules: null (missing) and false are false,
-// everything else is true. See: https://github.com/toolkitchen/mdv/issues/59
-bool _templateBooleanConversion(value) => null != value && false != value;
-
 class _CheckedBinding extends _InputBinding {
   _CheckedBinding(element, model, path) : super(element, model, path);
 
   void valueChanged(value) {
-    element.checked = _templateBooleanConversion(value);
+    element.checked = _Bindings._toBoolean(value);
   }
 
   void updateBinding(e) {
@@ -26947,220 +28027,309 @@
       }
     }
   }
-}
 
-// TODO(jmesserly): polyfill document.contains API instead of doing it here
-bool _isNodeInDocument(Node node) {
-  // On non-IE this works:
-  // return node.document.contains(node);
-  var document = node.document;
-  if (node == document || node.parentNode == document) return true;
-  return document.documentElement.contains(node);
-}
-
-// |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
-// Returns an array containing all radio buttons other than |element| that
-// have the same |name|, either in the form that |element| belongs to or,
-// if no form, in the document tree to which |element| belongs.
-//
-// This implementation is based upon the HTML spec definition of a
-// "radio button group":
-//   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
-//
-Iterable _getAssociatedRadioButtons(element) {
-  if (!_isNodeInDocument(element)) return [];
-  if (element.form != null) {
-    return element.form.nodes.where((el) {
-      return el != element &&
-          el is InputElement &&
-          el.type == 'radio' &&
-          el.name == element.name;
-    });
-  } else {
-    var radios = element.document.queryAll(
-        'input[type="radio"][name="${element.name}"]');
-    return radios.where((el) => el != element && el.form == null);
-  }
-}
-
-Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
-  var clone = node.clone(false); // Shallow clone.
-  if (clone is Element && clone.isTemplate) {
-    TemplateElement.decorate(clone, node);
-    if (syntax != null) {
-      clone.attributes.putIfAbsent('syntax', () => syntax);
-    }
-  }
-
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
-  }
-  return clone;
-}
-
-// http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-Document _getTemplateContentsOwner(Document doc) {
-  if (doc.window == null) {
-    return doc;
-  }
-  var d = doc._templateContentsOwner;
-  if (d == null) {
-    // TODO(arv): This should either be a Document or HTMLDocument depending
-    // on doc.
-    d = doc.implementation.createHtmlDocument('');
-    while (d.$dom_lastChild != null) {
-      d.$dom_lastChild.remove();
-    }
-    doc._templateContentsOwner = d;
-  }
-  return d;
-}
-
-Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
-  var clone = templateElement.clone(false);
-  var attributes = templateElement.attributes;
-  for (var name in attributes.keys.toList()) {
-    switch (name) {
-      case 'template':
-      case 'repeat':
-      case 'bind':
-      case 'ref':
-        clone.attributes.remove(name);
-        break;
-      default:
-        attributes.remove(name);
-        break;
-    }
-  }
-
-  return clone;
-}
-
-void _liftNonNativeTemplateChildrenIntoContent(Element templateElement) {
-  var content = templateElement.content;
-
-  if (!templateElement._isAttributeTemplate) {
-    var child;
-    while ((child = templateElement.$dom_firstChild) != null) {
-      content.append(child);
-    }
-    return;
-  }
-
-  // For attribute templates we copy the whole thing into the content and
-  // we move the non template attributes into the content.
+  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
+  // Returns an array containing all radio buttons other than |element| that
+  // have the same |name|, either in the form that |element| belongs to or,
+  // if no form, in the document tree to which |element| belongs.
   //
-  //   <tr foo template>
+  // This implementation is based upon the HTML spec definition of a
+  // "radio button group":
+  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
   //
-  // becomes
-  //
-  //   <tr template>
-  //   + #document-fragment
-  //     + <tr foo>
-  //
-  var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
-  var child;
-  while ((child = templateElement.$dom_firstChild) != null) {
-    newRoot.append(child);
-  }
-  content.append(newRoot);
-}
-
-void _bootstrapTemplatesRecursivelyFrom(Node node) {
-  void bootstrap(template) {
-    if (!TemplateElement.decorate(template)) {
-      _bootstrapTemplatesRecursivelyFrom(template.content);
+  static Iterable _getAssociatedRadioButtons(element) {
+    if (!_isNodeInDocument(element)) return [];
+    if (element.form != null) {
+      return element.form.nodes.where((el) {
+        return el != element &&
+            el is InputElement &&
+            el.type == 'radio' &&
+            el.name == element.name;
+      });
+    } else {
+      var radios = element.document.queryAll(
+          'input[type="radio"][name="${element.name}"]');
+      return radios.where((el) => el != element && el.form == null);
     }
   }
 
-  // Need to do this first as the contents may get lifted if |node| is
-  // template.
-  // TODO(jmesserly): node is DocumentFragment or Element
-  var templateDescendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-  if (node is Element && node.isTemplate) bootstrap(node);
-
-  templateDescendents.forEach(bootstrap);
-}
-
-final String _allTemplatesSelectors = 'template, option[template], ' +
-    Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
-  if (node is Element) {
-    _addAttributeBindings(node, model, syntax);
-  } else if (node is Text) {
-    _parseAndBind(node, 'text', node.text, model, syntax);
-  }
-
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    _addBindings(c, model, syntax);
+  // TODO(jmesserly): polyfill document.contains API instead of doing it here
+  static bool _isNodeInDocument(Node node) {
+    // On non-IE this works:
+    // return node.document.contains(node);
+    var document = node.document;
+    if (node == document || node.parentNode == document) return true;
+    return document.documentElement.contains(node);
   }
 }
 
+class _Bindings {
+  // TODO(jmesserly): not sure what kind of boolean conversion rules to
+  // apply for template data-binding. HTML attributes are true if they're
+  // present. However Dart only treats "true" as true. Since this is HTML we'll
+  // use something closer to the HTML rules: null (missing) and false are false,
+  // everything else is true. See: https://github.com/polymer-project/mdv/issues/59
+  static bool _toBoolean(value) => null != value && false != value;
 
-void _addAttributeBindings(Element element, model, syntax) {
-  element.attributes.forEach((name, value) {
-    if (value == '' && (name == 'bind' || name == 'repeat')) {
-      value = '{{}}';
-    }
-    _parseAndBind(element, name, value, model, syntax);
-  });
-}
-
-void _parseAndBind(Node node, String name, String text, model,
-    CustomBindingSyntax syntax) {
-
-  var tokens = _parseMustacheTokens(text);
-  if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
-    return;
-  }
-
-  if (tokens.length == 1 && tokens[0].isBinding) {
-    _bindOrDelegate(node, name, model, tokens[0].value, syntax);
-    return;
-  }
-
-  var replacementBinding = new CompoundBinding();
-  for (var i = 0; i < tokens.length; i++) {
-    var token = tokens[i];
-    if (token.isBinding) {
-      _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
-    }
-  }
-
-  replacementBinding.combinator = (values) {
-    var newValue = new StringBuffer();
-
-    for (var i = 0; i < tokens.length; i++) {
-      var token = tokens[i];
-      if (token.isText) {
-        newValue.write(token.value);
-      } else {
-        var value = values[i];
-        if (value != null) {
-          newValue.write(value);
-        }
+  static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
+    var clone = node.clone(false); // Shallow clone.
+    if (clone is Element && clone.isTemplate) {
+      TemplateElement.decorate(clone, node);
+      if (syntax != null) {
+        clone.attributes.putIfAbsent('syntax', () => syntax);
       }
     }
 
-    return newValue.toString();
-  };
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
+    }
+    return clone;
+  }
 
-  node.bind(name, replacementBinding, 'value');
-}
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  static Document _getTemplateContentsOwner(Document doc) {
+    if (doc.window == null) {
+      return doc;
+    }
+    var d = doc._templateContentsOwner;
+    if (d == null) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHtmlDocument('');
+      while (d.$dom_lastChild != null) {
+        d.$dom_lastChild.remove();
+      }
+      doc._templateContentsOwner = d;
+    }
+    return d;
+  }
 
-void _bindOrDelegate(node, name, model, String path,
-    CustomBindingSyntax syntax) {
+  static Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
+    var clone = templateElement.clone(false);
+    var attributes = templateElement.attributes;
+    for (var name in attributes.keys.toList()) {
+      switch (name) {
+        case 'template':
+        case 'repeat':
+        case 'bind':
+        case 'ref':
+          clone.attributes.remove(name);
+          break;
+        default:
+          attributes.remove(name);
+          break;
+      }
+    }
 
-  if (syntax != null) {
-    var delegateBinding = syntax.getBinding(model, path, name, node);
-    if (delegateBinding != null) {
-      model = delegateBinding;
-      path = 'value';
+    return clone;
+  }
+
+  static void _liftNonNativeChildrenIntoContent(Element templateElement) {
+    var content = templateElement.content;
+
+    if (!templateElement._isAttributeTemplate) {
+      var child;
+      while ((child = templateElement.$dom_firstChild) != null) {
+        content.append(child);
+      }
+      return;
+    }
+
+    // For attribute templates we copy the whole thing into the content and
+    // we move the non template attributes into the content.
+    //
+    //   <tr foo template>
+    //
+    // becomes
+    //
+    //   <tr template>
+    //   + #document-fragment
+    //     + <tr foo>
+    //
+    var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
+    var child;
+    while ((child = templateElement.$dom_firstChild) != null) {
+      newRoot.append(child);
+    }
+    content.append(newRoot);
+  }
+
+  static void _bootstrapTemplatesRecursivelyFrom(Node node) {
+    void bootstrap(template) {
+      if (!TemplateElement.decorate(template)) {
+        _bootstrapTemplatesRecursivelyFrom(template.content);
+      }
+    }
+
+    // Need to do this first as the contents may get lifted if |node| is
+    // template.
+    // TODO(jmesserly): node is DocumentFragment or Element
+    var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
+    if (node is Element && node.isTemplate) bootstrap(node);
+
+    descendents.forEach(bootstrap);
+  }
+
+  static final String _allTemplatesSelectors = 'template, option[template], ' +
+      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
+
+  static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
+    if (node is Element) {
+      _addAttributeBindings(node, model, syntax);
+    } else if (node is Text) {
+      _parseAndBind(node, 'text', node.text, model, syntax);
+    }
+
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      _addBindings(c, model, syntax);
     }
   }
 
-  node.bind(name, model, path);
+  static void _addAttributeBindings(Element element, model, syntax) {
+    element.attributes.forEach((name, value) {
+      if (value == '' && (name == 'bind' || name == 'repeat')) {
+        value = '{{}}';
+      }
+      _parseAndBind(element, name, value, model, syntax);
+    });
+  }
+
+  static void _parseAndBind(Node node, String name, String text, model,
+      CustomBindingSyntax syntax) {
+
+    var tokens = _parseMustacheTokens(text);
+    if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
+      return;
+    }
+
+    // If this is a custom element, give the .xtag a change to bind.
+    node = _nodeOrCustom(node);
+
+    if (tokens.length == 1 && tokens[0].isBinding) {
+      _bindOrDelegate(node, name, model, tokens[0].value, syntax);
+      return;
+    }
+
+    var replacementBinding = new CompoundBinding();
+    for (var i = 0; i < tokens.length; i++) {
+      var token = tokens[i];
+      if (token.isBinding) {
+        _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
+      }
+    }
+
+    replacementBinding.combinator = (values) {
+      var newValue = new StringBuffer();
+
+      for (var i = 0; i < tokens.length; i++) {
+        var token = tokens[i];
+        if (token.isText) {
+          newValue.write(token.value);
+        } else {
+          var value = values[i];
+          if (value != null) {
+            newValue.write(value);
+          }
+        }
+      }
+
+      return newValue.toString();
+    };
+
+    node.bind(name, replacementBinding, 'value');
+  }
+
+  static void _bindOrDelegate(node, name, model, String path,
+      CustomBindingSyntax syntax) {
+
+    if (syntax != null) {
+      var delegateBinding = syntax.getBinding(model, path, name, node);
+      if (delegateBinding != null) {
+        model = delegateBinding;
+        path = 'value';
+      }
+    }
+
+    node.bind(name, model, path);
+  }
+
+  /**
+   * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
+   * the node. This is used so nodes can override [Node.bind], [Node.unbind],
+   * and [Node.unbindAll] like InputElement does.
+   */
+  // TODO(jmesserly): remove this when we can extend Element for real.
+  static _nodeOrCustom(node) => node is Element ? node.xtag : node;
+
+  static List<_BindingToken> _parseMustacheTokens(String s) {
+    var result = [];
+    var length = s.length;
+    var index = 0, lastIndex = 0;
+    while (lastIndex < length) {
+      index = s.indexOf('{{', lastIndex);
+      if (index < 0) {
+        result.add(new _BindingToken(s.substring(lastIndex)));
+        break;
+      } else {
+        // There is a non-empty text run before the next path token.
+        if (index > 0 && lastIndex < index) {
+          result.add(new _BindingToken(s.substring(lastIndex, index)));
+        }
+        lastIndex = index + 2;
+        index = s.indexOf('}}', lastIndex);
+        if (index < 0) {
+          var text = s.substring(lastIndex - 2);
+          if (result.length > 0 && result.last.isText) {
+            result.last.value += text;
+          } else {
+            result.add(new _BindingToken(text));
+          }
+          break;
+        }
+
+        var value = s.substring(lastIndex, index).trim();
+        result.add(new _BindingToken(value, isBinding: true));
+        lastIndex = index + 2;
+      }
+    }
+    return result;
+  }
+
+  static void _addTemplateInstanceRecord(fragment, model) {
+    if (fragment.$dom_firstChild == null) {
+      return;
+    }
+
+    var instanceRecord = new TemplateInstance(
+        fragment.$dom_firstChild, fragment.$dom_lastChild, model);
+
+    var node = instanceRecord.firstNode;
+    while (node != null) {
+      node._templateInstance = instanceRecord;
+      node = node.nextNode;
+    }
+  }
+
+  static void _removeAllBindingsRecursively(Node node) {
+    _nodeOrCustom(node).unbindAll();
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      _removeAllBindingsRecursively(c);
+    }
+  }
+
+  static void _removeChild(Node parent, Node child) {
+    child._templateInstance = null;
+    if (child is Element && child.isTemplate) {
+      // Make sure we stop observing when we remove an element.
+      var templateIterator = child._templateIterator;
+      if (templateIterator != null) {
+        templateIterator.abandon();
+        child._templateIterator = null;
+      }
+    }
+    child.remove();
+    _removeAllBindingsRecursively(child);
+  }
 }
 
 class _BindingToken {
@@ -27172,77 +28341,6 @@
   bool get isText => !isBinding;
 }
 
-List<_BindingToken> _parseMustacheTokens(String s) {
-  var result = [];
-  var length = s.length;
-  var index = 0, lastIndex = 0;
-  while (lastIndex < length) {
-    index = s.indexOf('{{', lastIndex);
-    if (index < 0) {
-      result.add(new _BindingToken(s.substring(lastIndex)));
-      break;
-    } else {
-      // There is a non-empty text run before the next path token.
-      if (index > 0 && lastIndex < index) {
-        result.add(new _BindingToken(s.substring(lastIndex, index)));
-      }
-      lastIndex = index + 2;
-      index = s.indexOf('}}', lastIndex);
-      if (index < 0) {
-        var text = s.substring(lastIndex - 2);
-        if (result.length > 0 && result.last.isText) {
-          result.last.value += text;
-        } else {
-          result.add(new _BindingToken(text));
-        }
-        break;
-      }
-
-      var value = s.substring(lastIndex, index).trim();
-      result.add(new _BindingToken(value, isBinding: true));
-      lastIndex = index + 2;
-    }
-  }
-  return result;
-}
-
-void _addTemplateInstanceRecord(fragment, model) {
-  if (fragment.$dom_firstChild == null) {
-    return;
-  }
-
-  var instanceRecord = new TemplateInstance(
-      fragment.$dom_firstChild, fragment.$dom_lastChild, model);
-
-  var node = instanceRecord.firstNode;
-  while (node != null) {
-    node._templateInstance = instanceRecord;
-    node = node.nextNode;
-  }
-}
-
-void _removeAllBindingsRecursively(Node node) {
-  node.unbindAll();
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    _removeAllBindingsRecursively(c);
-  }
-}
-
-void _removeTemplateChild(Node parent, Node child) {
-  child._templateInstance = null;
-  if (child is Element && child.isTemplate) {
-    // Make sure we stop observing when we remove an element.
-    var templateIterator = child._templateIterator;
-    if (templateIterator != null) {
-      templateIterator.abandon();
-      child._templateIterator = null;
-    }
-  }
-  child.remove();
-  _removeAllBindingsRecursively(child);
-}
-
-
 class _TemplateIterator {
   final Element _templateElement;
   final List<Node> terminators = [];
@@ -27259,7 +28357,7 @@
   }
 
   static Object resolveInputs(Map values) {
-    if (values.containsKey('if') && !_templateBooleanConversion(values['if'])) {
+    if (values.containsKey('if') && !_Bindings._toBoolean(values['if'])) {
       return null;
     }
 
@@ -27320,7 +28418,7 @@
     while (terminator != previousTerminator) {
       var node = terminator;
       terminator = node.previousNode;
-      _removeTemplateChild(parent, node);
+      _Bindings._removeChild(parent, node);
     }
   }
 
@@ -27335,7 +28433,7 @@
     while (terminator != previousTerminator) {
       var node = terminator;
       terminator = node.previousNode;
-      _removeTemplateChild(parent, node);
+      _Bindings._removeChild(parent, node);
     }
   }
 
@@ -27377,8 +28475,8 @@
 
         var fragment = getInstanceFragment(syntax);
 
-        _addBindings(fragment, model, syntax);
-        _addTemplateInstanceRecord(fragment, model);
+        _Bindings._addBindings(fragment, model, syntax);
+        _Bindings._addTemplateInstanceRecord(fragment, model);
 
         insertInstanceAt(addIndex, fragment);
       }
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index 022e84b..3fcee62 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -5,6 +5,7 @@
 part of dart.io;
 
 // Constants used when working with native ports.
+// These must match the constants in runtime/bin/dartutils.h class CObject.
 const int _SUCCESS_RESPONSE = 0;
 const int _ILLEGAL_ARGUMENT_RESPONSE = 1;
 const int _OSERROR_RESPONSE = 2;
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index b97b458..15fbded 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -200,6 +200,7 @@
 const int _LINK_TARGET_REQUEST = 21;
 const int _TYPE_REQUEST = 22;
 const int _IDENTICAL_REQUEST = 23;
+const int _STAT_REQUEST = 24;
 
 // TODO(ager): The only reason for this class is that the patching
 // mechanism doesn't seem to like patching a private top level
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 847b7d1..4347f2c 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -22,6 +22,139 @@
 }
 
 /**
+ * A FileStat object represents the result of calling the POSIX stat() function
+ * on a file system object.  It is an immutable object, representing the
+ * snapshotted values returned by the stat() call.
+ */
+class FileStat {
+  // These must agree with enum FileStat in file.h.
+  static const _TYPE = 0;
+  static const _CHANGED_TIME = 1;
+  static const _MODIFIED_TIME = 2;
+  static const _ACCESSED_TIME = 3;
+  static const _MODE = 4;
+  static const _SIZE = 5;
+
+  FileStat._internal(this.changed,
+                     this.modified,
+                     this.accessed,
+                     this.type,
+                     this.mode,
+                     this.size);
+
+  external static List<int> _statSync(String path);
+
+
+  /**
+   * Call the operating system's stat() function on [path].
+   * Returns a [FileStat] object containing the data returned by stat().
+   * If the call fails, returns a [FileStat] object with .type set to
+   * FileSystemEntityType.NOT_FOUND and the other fields invalid.
+   */
+  static FileStat statSync(String path) {
+    var data = _statSync(path);
+    if (data is Error) throw data;
+    return new FileStat._internal(
+        new DateTime.fromMillisecondsSinceEpoch(data[_CHANGED_TIME] * 1000),
+        new DateTime.fromMillisecondsSinceEpoch(data[_MODIFIED_TIME] * 1000),
+        new DateTime.fromMillisecondsSinceEpoch(data[_ACCESSED_TIME] * 1000),
+        FileSystemEntityType._lookup(data[_TYPE]),
+        data[_MODE],
+        data[_SIZE]);
+  }
+
+  /**
+   * Asynchronously call the operating system's stat() function on [path].
+   * Returns a Future which completes with a [FileStat] object containing
+   * the data returned by stat().
+   * If the call fails, completes the future with a [FileStat] object with
+   * .type set to FileSystemEntityType.NOT_FOUND and the other fields invalid.
+   */
+  static Future<FileStat> stat(String path) {
+    // Get a new file service port for each request.  We could also cache one.
+    var service = _FileUtils._newServicePort();
+    List request = new List(2);
+    request[0] = _STAT_REQUEST;
+    request[1] = path;
+    return service.call(request).then((response) {
+      if (_isErrorResponse(response)) {
+        throw _exceptionFromResponse(response,
+                                     "Error getting stat of '$path'");
+      }
+      // Unwrap the real list from the "I'm not an error" wrapper.
+      List data = response[1];
+      return new FileStat._internal(
+          new DateTime.fromMillisecondsSinceEpoch(data[_CHANGED_TIME] * 1000),
+          new DateTime.fromMillisecondsSinceEpoch(data[_MODIFIED_TIME] * 1000),
+          new DateTime.fromMillisecondsSinceEpoch(data[_ACCESSED_TIME] * 1000),
+          FileSystemEntityType._lookup(data[_TYPE]),
+          data[_MODE],
+          data[_SIZE]);
+    });
+  }
+
+  String toString() => """
+FileStat: type $type
+          changed $changed
+          modified $modified
+          accessed $accessed
+          mode ${modeString()}
+          size $size""";
+
+  /**
+   * Returns the mode value as a human-readable string, in the format
+   * "rwxrwxrwx", reflecting the user, group, and world permissions to
+   * read, write, and execute the file system object, with "-" replacing the
+   * letter for missing permissions.  Extra permission bits may be represented
+   * by prepending "(suid)", "(guid)", and/or "(sticky)" to the mode string.
+   */
+  String modeString() {
+    var permissions = mode & 0xFFF;
+    var codes = const ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx'];
+    var result = [];
+    if ((permissions & 0x800) != 0) result.add("(suid) ");
+    if ((permissions & 0x400) != 0) result.add("(guid) ");
+    if ((permissions & 0x200) != 0) result.add("(sticky) ");
+    result.add(codes[(permissions >> 6) & 0x7]);
+    result.add(codes[(permissions >> 3) & 0x7]);
+    result.add(codes[permissions & 0x7]);
+    return result.join();
+  }
+
+  /**
+   * The time of the last change to the data or metadata of the file system
+   * object.  On Windows platforms, this is instead the file creation time.
+   */
+  final DateTime changed;
+  /**
+   * The time of the last change to the data of the file system
+   * object.
+   */
+  final DateTime modified;
+  /**
+   * The time of the last access to the data of the file system
+   * object.  On Windows platforms, this may have 1 day granularity, and be
+   * out of date by an hour.
+   */
+  final DateTime accessed;
+  /**
+   * The type of the object (file, directory, or link).  If the call to
+   * stat() fails, the type of the returned object is NOT_FOUND.
+   */
+  final FileSystemEntityType type;
+  /**
+   * The mode of the file system object.  Permissions are encoded in the lower
+   * 16 bits of this number, and can be decoded using the [modeString] getter.
+   */
+  final int mode;
+  /**
+   * The size of the file system object.
+   */
+  final int size;
+}
+
+
+/**
  * A [FileSystemEntity] is a common super class for [File] and
  * [Directory] objects.
  *
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index a2bba24..ae4f720 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -7,6 +7,7 @@
 import 'dart:html_common';
 import 'dart:_js_helper' show Creates, Returns, JavaScriptIndexingBehavior, JSName;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show Interceptor;
 // DO NOT EDIT - unless you are editing documentation as per:
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:svg library.
@@ -15,7 +16,6 @@
 
 
 
-
 // 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.
@@ -189,14 +189,24 @@
 @DomName('SVGAngle')
 class Angle native "SVGAngle" {
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_DEG')
+  @DocsEditable
   static const int SVG_ANGLETYPE_DEG = 2;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_GRAD')
+  @DocsEditable
   static const int SVG_ANGLETYPE_GRAD = 4;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_RAD')
+  @DocsEditable
   static const int SVG_ANGLETYPE_RAD = 3;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_ANGLETYPE_UNKNOWN = 0;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_UNSPECIFIED')
+  @DocsEditable
   static const int SVG_ANGLETYPE_UNSPECIFIED = 1;
 
   @DomName('SVGAngle.unitType')
@@ -1346,16 +1356,28 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => SvgElement.isTagSupported('feBlend') && (new SvgElement.tag('feBlend') is FEBlendElement);
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_DARKEN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_DARKEN = 4;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_LIGHTEN = 5;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_MULTIPLY')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_MULTIPLY = 2;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_NORMAL')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_NORMAL = 1;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_SCREEN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_SCREEN = 3;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_UNKNOWN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_UNKNOWN = 0;
 
   @DomName('SVGFEBlendElement.in1')
@@ -1412,14 +1434,24 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => SvgElement.isTagSupported('feColorMatrix') && (new SvgElement.tag('feColorMatrix') is FEColorMatrixElement);
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_HUEROTATE')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_HUEROTATE = 3;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_MATRIX = 1;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_SATURATE = 2;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0;
 
   @DomName('SVGFEColorMatrixElement.in1')
@@ -1511,18 +1543,32 @@
 @DomName('SVGFECompositeElement')
 class FECompositeElement extends StyledElement implements FilterPrimitiveStandardAttributes native "SVGFECompositeElement" {
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ATOP')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_ATOP = 4;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_IN')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_IN = 2;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OUT')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_OUT = 3;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_OVER = 1;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_UNKNOWN')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_XOR = 5;
 
   @DomName('SVGFECompositeElement.in1')
@@ -1595,12 +1641,20 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => SvgElement.isTagSupported('feConvolveMatrix') && (new SvgElement.tag('feConvolveMatrix') is FEConvolveMatrixElement);
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_DUPLICATE')
+  @DocsEditable
   static const int SVG_EDGEMODE_DUPLICATE = 1;
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE')
+  @DocsEditable
   static const int SVG_EDGEMODE_NONE = 3;
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_UNKNOWN')
+  @DocsEditable
   static const int SVG_EDGEMODE_UNKNOWN = 0;
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP')
+  @DocsEditable
   static const int SVG_EDGEMODE_WRAP = 2;
 
   @DomName('SVGFEConvolveMatrixElement.bias')
@@ -1755,14 +1809,24 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => SvgElement.isTagSupported('feDisplacementMap') && (new SvgElement.tag('feDisplacementMap') is FEDisplacementMapElement);
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_A')
+  @DocsEditable
   static const int SVG_CHANNEL_A = 4;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_B')
+  @DocsEditable
   static const int SVG_CHANNEL_B = 3;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_G')
+  @DocsEditable
   static const int SVG_CHANNEL_G = 2;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_R')
+  @DocsEditable
   static const int SVG_CHANNEL_R = 1;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_UNKNOWN')
+  @DocsEditable
   static const int SVG_CHANNEL_UNKNOWN = 0;
 
   @DomName('SVGFEDisplacementMapElement.in1')
@@ -2162,10 +2226,16 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 class FEMorphologyElement extends StyledElement implements FilterPrimitiveStandardAttributes native "SVGFEMorphologyElement" {
 
+  @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE')
+  @DocsEditable
   static const int SVG_MORPHOLOGY_OPERATOR_DILATE = 2;
 
+  @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_ERODE')
+  @DocsEditable
   static const int SVG_MORPHOLOGY_OPERATOR_ERODE = 1;
 
+  @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_UNKNOWN')
+  @DocsEditable
   static const int SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0;
 
   @DomName('SVGFEMorphologyElement.in1')
@@ -2472,16 +2542,28 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => SvgElement.isTagSupported('feTurbulence') && (new SvgElement.tag('feTurbulence') is FETurbulenceElement);
 
+  @DomName('SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH')
+  @DocsEditable
   static const int SVG_STITCHTYPE_NOSTITCH = 2;
 
+  @DomName('SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH')
+  @DocsEditable
   static const int SVG_STITCHTYPE_STITCH = 1;
 
+  @DomName('SVGFETurbulenceElement.SVG_STITCHTYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_STITCHTYPE_UNKNOWN = 0;
 
+  @DomName('SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE')
+  @DocsEditable
   static const int SVG_TURBULENCE_TYPE_FRACTALNOISE = 1;
 
+  @DomName('SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE')
+  @DocsEditable
   static const int SVG_TURBULENCE_TYPE_TURBULENCE = 2;
 
+  @DomName('SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_TURBULENCE_TYPE_UNKNOWN = 0;
 
   @DomName('SVGFETurbulenceElement.baseFrequencyX')
@@ -2953,26 +3035,48 @@
 @DomName('SVGLength')
 class Length native "SVGLength" {
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_CM')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_CM = 6;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_EMS')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_EMS = 3;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_EXS')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_EXS = 4;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_IN')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_IN = 8;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_MM')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_MM = 7;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_NUMBER')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_NUMBER = 1;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PC')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PC = 10;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PERCENTAGE')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PERCENTAGE = 2;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PT')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PT = 9;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PX')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PX = 5;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_UNKNOWN = 0;
 
   @DomName('SVGLength.unitType')
@@ -3006,14 +3110,18 @@
 
 @DocsEditable
 @DomName('SVGLengthList')
-class LengthList extends Object with ListMixin<Length>, ImmutableListMixin<Length> implements JavaScriptIndexingBehavior, List<Length> native "SVGLengthList" {
+class LengthList extends Interceptor with ListMixin<Length>, ImmutableListMixin<Length> implements JavaScriptIndexingBehavior, List<Length> native "SVGLengthList" {
 
   @DomName('SVGLengthList.numberOfItems')
   @DocsEditable
   final int numberOfItems;
 
-  Length operator[](int index) => this.getItem(index);
-
+  Length operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return this.getItem(index);
+  }
   void operator[]=(int index, Length value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -3027,6 +3135,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Length get first {
+    if (this.length > 0) {
+      return JS('Length', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Length get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Length', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Length get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Length', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Length elementAt(int index) => this[index];
   // -- end List<Length> mixins.
 
   @DomName('SVGLengthList.appendItem')
@@ -3216,16 +3349,28 @@
   @DocsEditable
   factory MarkerElement() => _SvgElementFactoryProvider.createSvgElement_tag("marker");
 
+  @DomName('SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH')
+  @DocsEditable
   static const int SVG_MARKERUNITS_STROKEWIDTH = 2;
 
+  @DomName('SVGMarkerElement.SVG_MARKERUNITS_UNKNOWN')
+  @DocsEditable
   static const int SVG_MARKERUNITS_UNKNOWN = 0;
 
+  @DomName('SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE')
+  @DocsEditable
   static const int SVG_MARKERUNITS_USERSPACEONUSE = 1;
 
+  @DomName('SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE')
+  @DocsEditable
   static const int SVG_MARKER_ORIENT_ANGLE = 2;
 
+  @DomName('SVGMarkerElement.SVG_MARKER_ORIENT_AUTO')
+  @DocsEditable
   static const int SVG_MARKER_ORIENT_AUTO = 1;
 
+  @DomName('SVGMarkerElement.SVG_MARKER_ORIENT_UNKNOWN')
+  @DocsEditable
   static const int SVG_MARKER_ORIENT_UNKNOWN = 0;
 
   @DomName('SVGMarkerElement.markerHeight')
@@ -3467,14 +3612,18 @@
 
 @DocsEditable
 @DomName('SVGNumberList')
-class NumberList extends Object with ListMixin<Number>, ImmutableListMixin<Number> implements JavaScriptIndexingBehavior, List<Number> native "SVGNumberList" {
+class NumberList extends Interceptor with ListMixin<Number>, ImmutableListMixin<Number> implements JavaScriptIndexingBehavior, List<Number> native "SVGNumberList" {
 
   @DomName('SVGNumberList.numberOfItems')
   @DocsEditable
   final int numberOfItems;
 
-  Number operator[](int index) => this.getItem(index);
-
+  Number operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return this.getItem(index);
+  }
   void operator[]=(int index, Number value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -3488,6 +3637,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Number get first {
+    if (this.length > 0) {
+      return JS('Number', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Number get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Number', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Number get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Number', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Number elementAt(int index) => this[index];
   // -- end List<Number> mixins.
 
   @DomName('SVGNumberList.appendItem')
@@ -3735,44 +3909,84 @@
 @DomName('SVGPathSeg')
 class PathSeg native "SVGPathSeg" {
 
+  @DomName('SVGPathSeg.PATHSEG_ARC_ABS')
+  @DocsEditable
   static const int PATHSEG_ARC_ABS = 10;
 
+  @DomName('SVGPathSeg.PATHSEG_ARC_REL')
+  @DocsEditable
   static const int PATHSEG_ARC_REL = 11;
 
+  @DomName('SVGPathSeg.PATHSEG_CLOSEPATH')
+  @DocsEditable
   static const int PATHSEG_CLOSEPATH = 1;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_ABS = 6;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_REL = 7;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_ABS = 8;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_REL = 9;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_ABS')
+  @DocsEditable
   static const int PATHSEG_LINETO_ABS = 4;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS')
+  @DocsEditable
   static const int PATHSEG_LINETO_HORIZONTAL_ABS = 12;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL')
+  @DocsEditable
   static const int PATHSEG_LINETO_HORIZONTAL_REL = 13;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_REL')
+  @DocsEditable
   static const int PATHSEG_LINETO_REL = 5;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS')
+  @DocsEditable
   static const int PATHSEG_LINETO_VERTICAL_ABS = 14;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL')
+  @DocsEditable
   static const int PATHSEG_LINETO_VERTICAL_REL = 15;
 
+  @DomName('SVGPathSeg.PATHSEG_MOVETO_ABS')
+  @DocsEditable
   static const int PATHSEG_MOVETO_ABS = 2;
 
+  @DomName('SVGPathSeg.PATHSEG_MOVETO_REL')
+  @DocsEditable
   static const int PATHSEG_MOVETO_REL = 3;
 
+  @DomName('SVGPathSeg.PATHSEG_UNKNOWN')
+  @DocsEditable
   static const int PATHSEG_UNKNOWN = 0;
 
   @DomName('SVGPathSeg.pathSegType')
@@ -4159,14 +4373,18 @@
 
 @DocsEditable
 @DomName('SVGPathSegList')
-class PathSegList extends Object with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements JavaScriptIndexingBehavior, List<PathSeg> native "SVGPathSegList" {
+class PathSegList extends Interceptor with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements JavaScriptIndexingBehavior, List<PathSeg> native "SVGPathSegList" {
 
   @DomName('SVGPathSegList.numberOfItems')
   @DocsEditable
   final int numberOfItems;
 
-  PathSeg operator[](int index) => this.getItem(index);
-
+  PathSeg operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return this.getItem(index);
+  }
   void operator[]=(int index, PathSeg value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -4180,6 +4398,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  PathSeg get first {
+    if (this.length > 0) {
+      return JS('PathSeg', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  PathSeg get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('PathSeg', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  PathSeg get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('PathSeg', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  PathSeg elementAt(int index) => this[index];
   // -- end List<PathSeg> mixins.
 
   @DomName('SVGPathSegList.appendItem')
@@ -4584,32 +4827,60 @@
 @DomName('SVGPreserveAspectRatio')
 class PreserveAspectRatio native "SVGPreserveAspectRatio" {
 
+  @DomName('SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET')
+  @DocsEditable
   static const int SVG_MEETORSLICE_MEET = 1;
 
+  @DomName('SVGPreserveAspectRatio.SVG_MEETORSLICE_SLICE')
+  @DocsEditable
   static const int SVG_MEETORSLICE_SLICE = 2;
 
+  @DomName('SVGPreserveAspectRatio.SVG_MEETORSLICE_UNKNOWN')
+  @DocsEditable
   static const int SVG_MEETORSLICE_UNKNOWN = 0;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_NONE = 1;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_UNKNOWN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_UNKNOWN = 0;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMAX')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMAXYMAX = 10;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMID')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMAXYMID = 7;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMIN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMAXYMIN = 4;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMAX')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMIDYMAX = 9;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMIDYMID = 6;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMIN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMIDYMIN = 3;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMAX')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMINYMAX = 8;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMID')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMINYMID = 5;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMIN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMINYMIN = 2;
 
   @DomName('SVGPreserveAspectRatio.align')
@@ -4796,16 +5067,28 @@
 @DomName('SVGRenderingIntent')
 class RenderingIntent native "SVGRenderingIntent" {
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_ABSOLUTE_COLORIMETRIC')
+  @DocsEditable
   static const int RENDERING_INTENT_ABSOLUTE_COLORIMETRIC = 5;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_AUTO')
+  @DocsEditable
   static const int RENDERING_INTENT_AUTO = 1;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_PERCEPTUAL')
+  @DocsEditable
   static const int RENDERING_INTENT_PERCEPTUAL = 2;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_RELATIVE_COLORIMETRIC')
+  @DocsEditable
   static const int RENDERING_INTENT_RELATIVE_COLORIMETRIC = 3;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_SATURATION')
+  @DocsEditable
   static const int RENDERING_INTENT_SATURATION = 4;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_UNKNOWN')
+  @DocsEditable
   static const int RENDERING_INTENT_UNKNOWN = 0;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -4881,14 +5164,18 @@
 
 @DocsEditable
 @DomName('SVGStringList')
-class StringList extends Object with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List<String> native "SVGStringList" {
+class StringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List<String> native "SVGStringList" {
 
   @DomName('SVGStringList.numberOfItems')
   @DocsEditable
   final int numberOfItems;
 
-  String operator[](int index) => this.getItem(index);
-
+  String operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return this.getItem(index);
+  }
   void operator[]=(int index, String value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -4902,6 +5189,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  String get first {
+    if (this.length > 0) {
+      return JS('String', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  String get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('String', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  String get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('String', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  String elementAt(int index) => this[index];
   // -- end List<String> mixins.
 
   @DomName('SVGStringList.appendItem')
@@ -5149,10 +5461,16 @@
 @DomName('SVGException')
 class SvgException native "SVGException" {
 
+  @DomName('SVGException.SVG_INVALID_VALUE_ERR')
+  @DocsEditable
   static const int SVG_INVALID_VALUE_ERR = 1;
 
+  @DomName('SVGException.SVG_MATRIX_NOT_INVERTABLE')
+  @DocsEditable
   static const int SVG_MATRIX_NOT_INVERTABLE = 2;
 
+  @DomName('SVGException.SVG_WRONG_TYPE_ERR')
+  @DocsEditable
   static const int SVG_WRONG_TYPE_ERR = 0;
 
   @DomName('SVGException.code')
@@ -5588,10 +5906,16 @@
 @DomName('SVGTextContentElement')
 class TextContentElement extends StyledElement implements Tests, ExternalResourcesRequired, LangSpace native "SVGTextContentElement" {
 
+  @DomName('SVGTextContentElement.LENGTHADJUST_SPACING')
+  @DocsEditable
   static const int LENGTHADJUST_SPACING = 1;
 
+  @DomName('SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS')
+  @DocsEditable
   static const int LENGTHADJUST_SPACINGANDGLYPHS = 2;
 
+  @DomName('SVGTextContentElement.LENGTHADJUST_UNKNOWN')
+  @DocsEditable
   static const int LENGTHADJUST_UNKNOWN = 0;
 
   @DomName('SVGTextContentElement.lengthAdjust')
@@ -5728,16 +6052,28 @@
 @DomName('SVGTextPathElement')
 class TextPathElement extends TextContentElement implements UriReference native "SVGTextPathElement" {
 
+  @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN')
+  @DocsEditable
   static const int TEXTPATH_METHODTYPE_ALIGN = 1;
 
+  @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH')
+  @DocsEditable
   static const int TEXTPATH_METHODTYPE_STRETCH = 2;
 
+  @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_UNKNOWN')
+  @DocsEditable
   static const int TEXTPATH_METHODTYPE_UNKNOWN = 0;
 
+  @DomName('SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO')
+  @DocsEditable
   static const int TEXTPATH_SPACINGTYPE_AUTO = 1;
 
+  @DomName('SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT')
+  @DocsEditable
   static const int TEXTPATH_SPACINGTYPE_EXACT = 2;
 
+  @DomName('SVGTextPathElement.TEXTPATH_SPACINGTYPE_UNKNOWN')
+  @DocsEditable
   static const int TEXTPATH_SPACINGTYPE_UNKNOWN = 0;
 
   @DomName('SVGTextPathElement.method')
@@ -5819,18 +6155,32 @@
 @DomName('SVGTransform')
 class Transform native "SVGTransform" {
 
+  @DomName('SVGTransform.SVG_TRANSFORM_MATRIX')
+  @DocsEditable
   static const int SVG_TRANSFORM_MATRIX = 1;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_ROTATE')
+  @DocsEditable
   static const int SVG_TRANSFORM_ROTATE = 4;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_SCALE')
+  @DocsEditable
   static const int SVG_TRANSFORM_SCALE = 3;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_SKEWX')
+  @DocsEditable
   static const int SVG_TRANSFORM_SKEWX = 5;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_SKEWY')
+  @DocsEditable
   static const int SVG_TRANSFORM_SKEWY = 6;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_TRANSLATE')
+  @DocsEditable
   static const int SVG_TRANSFORM_TRANSLATE = 2;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_UNKNOWN')
+  @DocsEditable
   static const int SVG_TRANSFORM_UNKNOWN = 0;
 
   @DomName('SVGTransform.angle')
@@ -5876,14 +6226,18 @@
 
 @DocsEditable
 @DomName('SVGTransformList')
-class TransformList extends Object with ListMixin<Transform>, ImmutableListMixin<Transform> implements List<Transform>, JavaScriptIndexingBehavior native "SVGTransformList" {
+class TransformList extends Interceptor with ListMixin<Transform>, ImmutableListMixin<Transform> implements List<Transform>, JavaScriptIndexingBehavior native "SVGTransformList" {
 
   @DomName('SVGTransformList.numberOfItems')
   @DocsEditable
   final int numberOfItems;
 
-  Transform operator[](int index) => this.getItem(index);
-
+  Transform operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return this.getItem(index);
+  }
   void operator[]=(int index, Transform value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -5897,6 +6251,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Transform get first {
+    if (this.length > 0) {
+      return JS('Transform', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Transform get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Transform', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Transform get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Transform', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Transform elementAt(int index) => this[index];
   // -- end List<Transform> mixins.
 
   @DomName('SVGTransformList.appendItem')
@@ -5969,10 +6348,16 @@
 @DomName('SVGUnitTypes')
 class UnitTypes native "SVGUnitTypes" {
 
+  @DomName('SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX')
+  @DocsEditable
   static const int SVG_UNIT_TYPE_OBJECTBOUNDINGBOX = 2;
 
+  @DomName('SVGUnitTypes.SVG_UNIT_TYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_UNIT_TYPE_UNKNOWN = 0;
 
+  @DomName('SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE')
+  @DocsEditable
   static const int SVG_UNIT_TYPE_USERSPACEONUSE = 1;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -6188,10 +6573,16 @@
 @DomName('SVGZoomAndPan')
 abstract class ZoomAndPan {
 
+  @DomName('SVGZoomAndPan.SVG_ZOOMANDPAN_DISABLE')
+  @DocsEditable
   static const int SVG_ZOOMANDPAN_DISABLE = 1;
 
+  @DomName('SVGZoomAndPan.SVG_ZOOMANDPAN_MAGNIFY')
+  @DocsEditable
   static const int SVG_ZOOMANDPAN_MAGNIFY = 2;
 
+  @DomName('SVGZoomAndPan.SVG_ZOOMANDPAN_UNKNOWN')
+  @DocsEditable
   static const int SVG_ZOOMANDPAN_UNKNOWN = 0;
 
   int zoomAndPan;
@@ -6232,14 +6623,18 @@
 
 @DocsEditable
 @DomName('SVGElementInstanceList')
-class _ElementInstanceList extends Object with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements JavaScriptIndexingBehavior, List<ElementInstance> native "SVGElementInstanceList" {
+class _ElementInstanceList extends Interceptor with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements JavaScriptIndexingBehavior, List<ElementInstance> native "SVGElementInstanceList" {
 
   @DomName('SVGElementInstanceList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  ElementInstance operator[](int index) => this.item(index);
-
+  ElementInstance operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return this.item(index);
+  }
   void operator[]=(int index, ElementInstance value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -6251,6 +6646,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  ElementInstance get first {
+    if (this.length > 0) {
+      return JS('ElementInstance', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  ElementInstance get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('ElementInstance', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  ElementInstance get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('ElementInstance', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  ElementInstance elementAt(int index) => this[index];
   // -- end List<ElementInstance> mixins.
 
   @DomName('SVGElementInstanceList.item')
@@ -6266,12 +6686,20 @@
 @DomName('SVGGradientElement')
 class _GradientElement extends StyledElement implements UriReference, ExternalResourcesRequired native "SVGGradientElement" {
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_PAD')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_PAD = 1;
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_REFLECT')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_REFLECT = 2;
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_REPEAT')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_REPEAT = 3;
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_UNKNOWN')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_UNKNOWN = 0;
 
   @DomName('SVGGradientElement.gradientTransform')
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index 3310b73..bb2ad9b 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -197,14 +197,24 @@
 class Angle extends NativeFieldWrapperClass1 {
   Angle.internal();
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_DEG')
+  @DocsEditable
   static const int SVG_ANGLETYPE_DEG = 2;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_GRAD')
+  @DocsEditable
   static const int SVG_ANGLETYPE_GRAD = 4;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_RAD')
+  @DocsEditable
   static const int SVG_ANGLETYPE_RAD = 3;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_ANGLETYPE_UNKNOWN = 0;
 
+  @DomName('SVGAngle.SVG_ANGLETYPE_UNSPECIFIED')
+  @DocsEditable
   static const int SVG_ANGLETYPE_UNSPECIFIED = 1;
 
   @DomName('SVGAngle.unitType')
@@ -1480,16 +1490,28 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_DARKEN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_DARKEN = 4;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_LIGHTEN = 5;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_MULTIPLY')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_MULTIPLY = 2;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_NORMAL')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_NORMAL = 1;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_SCREEN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_SCREEN = 3;
 
+  @DomName('SVGFEBlendElement.SVG_FEBLEND_MODE_UNKNOWN')
+  @DocsEditable
   static const int SVG_FEBLEND_MODE_UNKNOWN = 0;
 
   @DomName('SVGFEBlendElement.in1')
@@ -1548,14 +1570,24 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_HUEROTATE')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_HUEROTATE = 3;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_MATRIX = 1;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_SATURATE = 2;
 
+  @DomName('SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0;
 
   @DomName('SVGFEColorMatrixElement.in1')
@@ -1651,18 +1683,32 @@
 class FECompositeElement extends StyledElement implements FilterPrimitiveStandardAttributes {
   FECompositeElement.internal() : super.internal();
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ATOP')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_ATOP = 4;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_IN')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_IN = 2;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OUT')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_OUT = 3;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_OVER = 1;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_UNKNOWN')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0;
 
+  @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR')
+  @DocsEditable
   static const int SVG_FECOMPOSITE_OPERATOR_XOR = 5;
 
   @DomName('SVGFECompositeElement.in1')
@@ -1737,12 +1783,20 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_DUPLICATE')
+  @DocsEditable
   static const int SVG_EDGEMODE_DUPLICATE = 1;
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE')
+  @DocsEditable
   static const int SVG_EDGEMODE_NONE = 3;
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_UNKNOWN')
+  @DocsEditable
   static const int SVG_EDGEMODE_UNKNOWN = 0;
 
+  @DomName('SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP')
+  @DocsEditable
   static const int SVG_EDGEMODE_WRAP = 2;
 
   @DomName('SVGFEConvolveMatrixElement.bias')
@@ -1901,14 +1955,24 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_A')
+  @DocsEditable
   static const int SVG_CHANNEL_A = 4;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_B')
+  @DocsEditable
   static const int SVG_CHANNEL_B = 3;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_G')
+  @DocsEditable
   static const int SVG_CHANNEL_G = 2;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_R')
+  @DocsEditable
   static const int SVG_CHANNEL_R = 1;
 
+  @DomName('SVGFEDisplacementMapElement.SVG_CHANNEL_UNKNOWN')
+  @DocsEditable
   static const int SVG_CHANNEL_UNKNOWN = 0;
 
   @DomName('SVGFEDisplacementMapElement.in1')
@@ -2344,10 +2408,16 @@
 class FEMorphologyElement extends StyledElement implements FilterPrimitiveStandardAttributes {
   FEMorphologyElement.internal() : super.internal();
 
+  @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE')
+  @DocsEditable
   static const int SVG_MORPHOLOGY_OPERATOR_DILATE = 2;
 
+  @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_ERODE')
+  @DocsEditable
   static const int SVG_MORPHOLOGY_OPERATOR_ERODE = 1;
 
+  @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_UNKNOWN')
+  @DocsEditable
   static const int SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0;
 
   @DomName('SVGFEMorphologyElement.in1')
@@ -2670,16 +2740,28 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH')
+  @DocsEditable
   static const int SVG_STITCHTYPE_NOSTITCH = 2;
 
+  @DomName('SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH')
+  @DocsEditable
   static const int SVG_STITCHTYPE_STITCH = 1;
 
+  @DomName('SVGFETurbulenceElement.SVG_STITCHTYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_STITCHTYPE_UNKNOWN = 0;
 
+  @DomName('SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE')
+  @DocsEditable
   static const int SVG_TURBULENCE_TYPE_FRACTALNOISE = 1;
 
+  @DomName('SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE')
+  @DocsEditable
   static const int SVG_TURBULENCE_TYPE_TURBULENCE = 2;
 
+  @DomName('SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_TURBULENCE_TYPE_UNKNOWN = 0;
 
   @DomName('SVGFETurbulenceElement.baseFrequencyX')
@@ -3198,26 +3280,48 @@
 class Length extends NativeFieldWrapperClass1 {
   Length.internal();
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_CM')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_CM = 6;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_EMS')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_EMS = 3;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_EXS')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_EXS = 4;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_IN')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_IN = 8;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_MM')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_MM = 7;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_NUMBER')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_NUMBER = 1;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PC')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PC = 10;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PERCENTAGE')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PERCENTAGE = 2;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PT')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PT = 9;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_PX')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_PX = 5;
 
+  @DomName('SVGLength.SVG_LENGTHTYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_LENGTHTYPE_UNKNOWN = 0;
 
   @DomName('SVGLength.unitType')
@@ -3273,7 +3377,12 @@
   @DocsEditable
   int get numberOfItems native "SVGLengthList_numberOfItems_Getter";
 
-  Length operator[](int index) native "SVGLengthList_item_Callback";
+  Length operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Length _nativeIndexedGetter(int index) native "SVGLengthList_item_Callback";
 
   void operator[]=(int index, Length value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -3288,6 +3397,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Length get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Length get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Length get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Length elementAt(int index) => this[index];
   // -- end List<Length> mixins.
 
   @DomName('SVGLengthList.appendItem')
@@ -3502,16 +3636,28 @@
   @DocsEditable
   factory MarkerElement() => _SvgElementFactoryProvider.createSvgElement_tag("marker");
 
+  @DomName('SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH')
+  @DocsEditable
   static const int SVG_MARKERUNITS_STROKEWIDTH = 2;
 
+  @DomName('SVGMarkerElement.SVG_MARKERUNITS_UNKNOWN')
+  @DocsEditable
   static const int SVG_MARKERUNITS_UNKNOWN = 0;
 
+  @DomName('SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE')
+  @DocsEditable
   static const int SVG_MARKERUNITS_USERSPACEONUSE = 1;
 
+  @DomName('SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE')
+  @DocsEditable
   static const int SVG_MARKER_ORIENT_ANGLE = 2;
 
+  @DomName('SVGMarkerElement.SVG_MARKER_ORIENT_AUTO')
+  @DocsEditable
   static const int SVG_MARKER_ORIENT_AUTO = 1;
 
+  @DomName('SVGMarkerElement.SVG_MARKER_ORIENT_UNKNOWN')
+  @DocsEditable
   static const int SVG_MARKER_ORIENT_UNKNOWN = 0;
 
   @DomName('SVGMarkerElement.markerHeight')
@@ -3811,7 +3957,12 @@
   @DocsEditable
   int get numberOfItems native "SVGNumberList_numberOfItems_Getter";
 
-  Number operator[](int index) native "SVGNumberList_item_Callback";
+  Number operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Number _nativeIndexedGetter(int index) native "SVGNumberList_item_Callback";
 
   void operator[]=(int index, Number value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -3826,6 +3977,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Number get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Number get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Number get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Number elementAt(int index) => this[index];
   // -- end List<Number> mixins.
 
   @DomName('SVGNumberList.appendItem')
@@ -4058,44 +4234,84 @@
 class PathSeg extends NativeFieldWrapperClass1 {
   PathSeg.internal();
 
+  @DomName('SVGPathSeg.PATHSEG_ARC_ABS')
+  @DocsEditable
   static const int PATHSEG_ARC_ABS = 10;
 
+  @DomName('SVGPathSeg.PATHSEG_ARC_REL')
+  @DocsEditable
   static const int PATHSEG_ARC_REL = 11;
 
+  @DomName('SVGPathSeg.PATHSEG_CLOSEPATH')
+  @DocsEditable
   static const int PATHSEG_CLOSEPATH = 1;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_ABS = 6;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_REL = 7;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_ABS = 8;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_REL = 9;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
 
+  @DomName('SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL')
+  @DocsEditable
   static const int PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_ABS')
+  @DocsEditable
   static const int PATHSEG_LINETO_ABS = 4;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS')
+  @DocsEditable
   static const int PATHSEG_LINETO_HORIZONTAL_ABS = 12;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL')
+  @DocsEditable
   static const int PATHSEG_LINETO_HORIZONTAL_REL = 13;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_REL')
+  @DocsEditable
   static const int PATHSEG_LINETO_REL = 5;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS')
+  @DocsEditable
   static const int PATHSEG_LINETO_VERTICAL_ABS = 14;
 
+  @DomName('SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL')
+  @DocsEditable
   static const int PATHSEG_LINETO_VERTICAL_REL = 15;
 
+  @DomName('SVGPathSeg.PATHSEG_MOVETO_ABS')
+  @DocsEditable
   static const int PATHSEG_MOVETO_ABS = 2;
 
+  @DomName('SVGPathSeg.PATHSEG_MOVETO_REL')
+  @DocsEditable
   static const int PATHSEG_MOVETO_REL = 3;
 
+  @DomName('SVGPathSeg.PATHSEG_UNKNOWN')
+  @DocsEditable
   static const int PATHSEG_UNKNOWN = 0;
 
   @DomName('SVGPathSeg.pathSegType')
@@ -4776,7 +4992,12 @@
   @DocsEditable
   int get numberOfItems native "SVGPathSegList_numberOfItems_Getter";
 
-  PathSeg operator[](int index) native "SVGPathSegList_item_Callback";
+  PathSeg operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  PathSeg _nativeIndexedGetter(int index) native "SVGPathSegList_item_Callback";
 
   void operator[]=(int index, PathSeg value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -4791,6 +5012,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  PathSeg get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  PathSeg get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  PathSeg get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  PathSeg elementAt(int index) => this[index];
   // -- end List<PathSeg> mixins.
 
   @DomName('SVGPathSegList.appendItem')
@@ -5241,32 +5487,60 @@
 class PreserveAspectRatio extends NativeFieldWrapperClass1 {
   PreserveAspectRatio.internal();
 
+  @DomName('SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET')
+  @DocsEditable
   static const int SVG_MEETORSLICE_MEET = 1;
 
+  @DomName('SVGPreserveAspectRatio.SVG_MEETORSLICE_SLICE')
+  @DocsEditable
   static const int SVG_MEETORSLICE_SLICE = 2;
 
+  @DomName('SVGPreserveAspectRatio.SVG_MEETORSLICE_UNKNOWN')
+  @DocsEditable
   static const int SVG_MEETORSLICE_UNKNOWN = 0;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_NONE = 1;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_UNKNOWN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_UNKNOWN = 0;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMAX')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMAXYMAX = 10;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMID')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMAXYMID = 7;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMIN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMAXYMIN = 4;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMAX')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMIDYMAX = 9;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMIDYMID = 6;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMIN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMIDYMIN = 3;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMAX')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMINYMAX = 8;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMID')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMINYMID = 5;
 
+  @DomName('SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMIN')
+  @DocsEditable
   static const int SVG_PRESERVEASPECTRATIO_XMINYMIN = 2;
 
   @DomName('SVGPreserveAspectRatio.align')
@@ -5489,16 +5763,28 @@
 class RenderingIntent extends NativeFieldWrapperClass1 {
   RenderingIntent.internal();
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_ABSOLUTE_COLORIMETRIC')
+  @DocsEditable
   static const int RENDERING_INTENT_ABSOLUTE_COLORIMETRIC = 5;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_AUTO')
+  @DocsEditable
   static const int RENDERING_INTENT_AUTO = 1;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_PERCEPTUAL')
+  @DocsEditable
   static const int RENDERING_INTENT_PERCEPTUAL = 2;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_RELATIVE_COLORIMETRIC')
+  @DocsEditable
   static const int RENDERING_INTENT_RELATIVE_COLORIMETRIC = 3;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_SATURATION')
+  @DocsEditable
   static const int RENDERING_INTENT_SATURATION = 4;
 
+  @DomName('SVGRenderingIntent.RENDERING_INTENT_UNKNOWN')
+  @DocsEditable
   static const int RENDERING_INTENT_UNKNOWN = 0;
 
 }
@@ -5595,7 +5881,12 @@
   @DocsEditable
   int get numberOfItems native "SVGStringList_numberOfItems_Getter";
 
-  String operator[](int index) native "SVGStringList_item_Callback";
+  String operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  String _nativeIndexedGetter(int index) native "SVGStringList_item_Callback";
 
   void operator[]=(int index, String value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -5610,6 +5901,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  String get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  String get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  String get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  String elementAt(int index) => this[index];
   // -- end List<String> mixins.
 
   @DomName('SVGStringList.appendItem')
@@ -5898,10 +6214,16 @@
 class SvgException extends NativeFieldWrapperClass1 {
   SvgException.internal();
 
+  @DomName('SVGException.SVG_INVALID_VALUE_ERR')
+  @DocsEditable
   static const int SVG_INVALID_VALUE_ERR = 1;
 
+  @DomName('SVGException.SVG_MATRIX_NOT_INVERTABLE')
+  @DocsEditable
   static const int SVG_MATRIX_NOT_INVERTABLE = 2;
 
+  @DomName('SVGException.SVG_WRONG_TYPE_ERR')
+  @DocsEditable
   static const int SVG_WRONG_TYPE_ERR = 0;
 
   @DomName('SVGException.code')
@@ -6361,10 +6683,16 @@
 class TextContentElement extends StyledElement implements Tests, ExternalResourcesRequired, LangSpace {
   TextContentElement.internal() : super.internal();
 
+  @DomName('SVGTextContentElement.LENGTHADJUST_SPACING')
+  @DocsEditable
   static const int LENGTHADJUST_SPACING = 1;
 
+  @DomName('SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS')
+  @DocsEditable
   static const int LENGTHADJUST_SPACINGANDGLYPHS = 2;
 
+  @DomName('SVGTextContentElement.LENGTHADJUST_UNKNOWN')
+  @DocsEditable
   static const int LENGTHADJUST_UNKNOWN = 0;
 
   @DomName('SVGTextContentElement.lengthAdjust')
@@ -6505,16 +6833,28 @@
 class TextPathElement extends TextContentElement implements UriReference {
   TextPathElement.internal() : super.internal();
 
+  @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN')
+  @DocsEditable
   static const int TEXTPATH_METHODTYPE_ALIGN = 1;
 
+  @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH')
+  @DocsEditable
   static const int TEXTPATH_METHODTYPE_STRETCH = 2;
 
+  @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_UNKNOWN')
+  @DocsEditable
   static const int TEXTPATH_METHODTYPE_UNKNOWN = 0;
 
+  @DomName('SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO')
+  @DocsEditable
   static const int TEXTPATH_SPACINGTYPE_AUTO = 1;
 
+  @DomName('SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT')
+  @DocsEditable
   static const int TEXTPATH_SPACINGTYPE_EXACT = 2;
 
+  @DomName('SVGTextPathElement.TEXTPATH_SPACINGTYPE_UNKNOWN')
+  @DocsEditable
   static const int TEXTPATH_SPACINGTYPE_UNKNOWN = 0;
 
   @DomName('SVGTextPathElement.method')
@@ -6612,18 +6952,32 @@
 class Transform extends NativeFieldWrapperClass1 {
   Transform.internal();
 
+  @DomName('SVGTransform.SVG_TRANSFORM_MATRIX')
+  @DocsEditable
   static const int SVG_TRANSFORM_MATRIX = 1;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_ROTATE')
+  @DocsEditable
   static const int SVG_TRANSFORM_ROTATE = 4;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_SCALE')
+  @DocsEditable
   static const int SVG_TRANSFORM_SCALE = 3;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_SKEWX')
+  @DocsEditable
   static const int SVG_TRANSFORM_SKEWX = 5;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_SKEWY')
+  @DocsEditable
   static const int SVG_TRANSFORM_SKEWY = 6;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_TRANSLATE')
+  @DocsEditable
   static const int SVG_TRANSFORM_TRANSLATE = 2;
 
+  @DomName('SVGTransform.SVG_TRANSFORM_UNKNOWN')
+  @DocsEditable
   static const int SVG_TRANSFORM_UNKNOWN = 0;
 
   @DomName('SVGTransform.angle')
@@ -6679,7 +7033,12 @@
   @DocsEditable
   int get numberOfItems native "SVGTransformList_numberOfItems_Getter";
 
-  Transform operator[](int index) native "SVGTransformList_item_Callback";
+  Transform operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Transform _nativeIndexedGetter(int index) native "SVGTransformList_item_Callback";
 
   void operator[]=(int index, Transform value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -6694,6 +7053,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Transform get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Transform get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Transform get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Transform elementAt(int index) => this[index];
   // -- end List<Transform> mixins.
 
   @DomName('SVGTransformList.appendItem')
@@ -6786,10 +7170,16 @@
 class UnitTypes extends NativeFieldWrapperClass1 {
   UnitTypes.internal();
 
+  @DomName('SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX')
+  @DocsEditable
   static const int SVG_UNIT_TYPE_OBJECTBOUNDINGBOX = 2;
 
+  @DomName('SVGUnitTypes.SVG_UNIT_TYPE_UNKNOWN')
+  @DocsEditable
   static const int SVG_UNIT_TYPE_UNKNOWN = 0;
 
+  @DomName('SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE')
+  @DocsEditable
   static const int SVG_UNIT_TYPE_USERSPACEONUSE = 1;
 
 }
@@ -7025,10 +7415,16 @@
 class ZoomAndPan extends NativeFieldWrapperClass1 {
   ZoomAndPan.internal();
 
+  @DomName('SVGZoomAndPan.SVG_ZOOMANDPAN_DISABLE')
+  @DocsEditable
   static const int SVG_ZOOMANDPAN_DISABLE = 1;
 
+  @DomName('SVGZoomAndPan.SVG_ZOOMANDPAN_MAGNIFY')
+  @DocsEditable
   static const int SVG_ZOOMANDPAN_MAGNIFY = 2;
 
+  @DomName('SVGZoomAndPan.SVG_ZOOMANDPAN_UNKNOWN')
+  @DocsEditable
   static const int SVG_ZOOMANDPAN_UNKNOWN = 0;
 
   @DomName('SVGZoomAndPan.zoomAndPan')
@@ -7089,7 +7485,12 @@
   @DocsEditable
   int get length native "SVGElementInstanceList_length_Getter";
 
-  ElementInstance operator[](int index) native "SVGElementInstanceList_item_Callback";
+  ElementInstance operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  ElementInstance _nativeIndexedGetter(int index) native "SVGElementInstanceList_item_Callback";
 
   void operator[]=(int index, ElementInstance value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -7102,6 +7503,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  ElementInstance get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  ElementInstance get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  ElementInstance get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  ElementInstance elementAt(int index) => this[index];
   // -- end List<ElementInstance> mixins.
 
   @DomName('SVGElementInstanceList.item')
@@ -7121,12 +7547,20 @@
 class _GradientElement extends StyledElement implements UriReference, ExternalResourcesRequired {
   _GradientElement.internal() : super.internal();
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_PAD')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_PAD = 1;
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_REFLECT')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_REFLECT = 2;
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_REPEAT')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_REPEAT = 3;
 
+  @DomName('SVGGradientElement.SVG_SPREADMETHOD_UNKNOWN')
+  @DocsEditable
   static const int SVG_SPREADMETHOD_UNKNOWN = 0;
 
   @DomName('SVGGradientElement.gradientTransform')
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index 8192802..c6b7b82 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -8,6 +8,7 @@
 import 'dart:typed_data';
 import 'dart:_js_helper' show Creates, Returns, convertDartClosureToJS;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show Interceptor;
 // DO NOT EDIT - unless you are editing documentation as per:
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:audio library.
@@ -135,12 +136,20 @@
     }
   }
 
+  @DomName('AudioBufferSourceNode.FINISHED_STATE')
+  @DocsEditable
   static const int FINISHED_STATE = 3;
 
+  @DomName('AudioBufferSourceNode.PLAYING_STATE')
+  @DocsEditable
   static const int PLAYING_STATE = 2;
 
+  @DomName('AudioBufferSourceNode.SCHEDULED_STATE')
+  @DocsEditable
   static const int SCHEDULED_STATE = 1;
 
+  @DomName('AudioBufferSourceNode.UNSCHEDULED_STATE')
+  @DocsEditable
   static const int UNSCHEDULED_STATE = 0;
 
   @DomName('AudioBufferSourceNode.buffer')
@@ -485,20 +494,36 @@
 @DomName('BiquadFilterNode')
 class BiquadFilterNode extends AudioNode native "BiquadFilterNode" {
 
+  @DomName('BiquadFilterNode.ALLPASS')
+  @DocsEditable
   static const int ALLPASS = 7;
 
+  @DomName('BiquadFilterNode.BANDPASS')
+  @DocsEditable
   static const int BANDPASS = 2;
 
+  @DomName('BiquadFilterNode.HIGHPASS')
+  @DocsEditable
   static const int HIGHPASS = 1;
 
+  @DomName('BiquadFilterNode.HIGHSHELF')
+  @DocsEditable
   static const int HIGHSHELF = 4;
 
+  @DomName('BiquadFilterNode.LOWPASS')
+  @DocsEditable
   static const int LOWPASS = 0;
 
+  @DomName('BiquadFilterNode.LOWSHELF')
+  @DocsEditable
   static const int LOWSHELF = 3;
 
+  @DomName('BiquadFilterNode.NOTCH')
+  @DocsEditable
   static const int NOTCH = 6;
 
+  @DomName('BiquadFilterNode.PEAKING')
+  @DocsEditable
   static const int PEAKING = 5;
 
   @DomName('BiquadFilterNode.Q')
@@ -696,22 +721,40 @@
 @DomName('OscillatorNode')
 class OscillatorNode extends AudioSourceNode native "OscillatorNode" {
 
+  @DomName('OscillatorNode.CUSTOM')
+  @DocsEditable
   static const int CUSTOM = 4;
 
+  @DomName('OscillatorNode.FINISHED_STATE')
+  @DocsEditable
   static const int FINISHED_STATE = 3;
 
+  @DomName('OscillatorNode.PLAYING_STATE')
+  @DocsEditable
   static const int PLAYING_STATE = 2;
 
+  @DomName('OscillatorNode.SAWTOOTH')
+  @DocsEditable
   static const int SAWTOOTH = 2;
 
+  @DomName('OscillatorNode.SCHEDULED_STATE')
+  @DocsEditable
   static const int SCHEDULED_STATE = 1;
 
+  @DomName('OscillatorNode.SINE')
+  @DocsEditable
   static const int SINE = 0;
 
+  @DomName('OscillatorNode.SQUARE')
+  @DocsEditable
   static const int SQUARE = 1;
 
+  @DomName('OscillatorNode.TRIANGLE')
+  @DocsEditable
   static const int TRIANGLE = 3;
 
+  @DomName('OscillatorNode.UNSCHEDULED_STATE')
+  @DocsEditable
   static const int UNSCHEDULED_STATE = 0;
 
   @DomName('OscillatorNode.detune')
@@ -751,16 +794,28 @@
 @DomName('PannerNode')
 class PannerNode extends AudioNode native "PannerNode" {
 
+  @DomName('PannerNode.EQUALPOWER')
+  @DocsEditable
   static const int EQUALPOWER = 0;
 
+  @DomName('PannerNode.EXPONENTIAL_DISTANCE')
+  @DocsEditable
   static const int EXPONENTIAL_DISTANCE = 2;
 
+  @DomName('PannerNode.HRTF')
+  @DocsEditable
   static const int HRTF = 1;
 
+  @DomName('PannerNode.INVERSE_DISTANCE')
+  @DocsEditable
   static const int INVERSE_DISTANCE = 1;
 
+  @DomName('PannerNode.LINEAR_DISTANCE')
+  @DocsEditable
   static const int LINEAR_DISTANCE = 0;
 
+  @DomName('PannerNode.SOUNDFIELD')
+  @DocsEditable
   static const int SOUNDFIELD = 2;
 
   @DomName('PannerNode.coneInnerAngle')
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index 950707c..d71875c 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -135,12 +135,20 @@
 class AudioBufferSourceNode extends AudioSourceNode {
   AudioBufferSourceNode.internal() : super.internal();
 
+  @DomName('AudioBufferSourceNode.FINISHED_STATE')
+  @DocsEditable
   static const int FINISHED_STATE = 3;
 
+  @DomName('AudioBufferSourceNode.PLAYING_STATE')
+  @DocsEditable
   static const int PLAYING_STATE = 2;
 
+  @DomName('AudioBufferSourceNode.SCHEDULED_STATE')
+  @DocsEditable
   static const int SCHEDULED_STATE = 1;
 
+  @DomName('AudioBufferSourceNode.UNSCHEDULED_STATE')
+  @DocsEditable
   static const int UNSCHEDULED_STATE = 0;
 
   @DomName('AudioBufferSourceNode.buffer')
@@ -620,20 +628,36 @@
 class BiquadFilterNode extends AudioNode {
   BiquadFilterNode.internal() : super.internal();
 
+  @DomName('BiquadFilterNode.ALLPASS')
+  @DocsEditable
   static const int ALLPASS = 7;
 
+  @DomName('BiquadFilterNode.BANDPASS')
+  @DocsEditable
   static const int BANDPASS = 2;
 
+  @DomName('BiquadFilterNode.HIGHPASS')
+  @DocsEditable
   static const int HIGHPASS = 1;
 
+  @DomName('BiquadFilterNode.HIGHSHELF')
+  @DocsEditable
   static const int HIGHSHELF = 4;
 
+  @DomName('BiquadFilterNode.LOWPASS')
+  @DocsEditable
   static const int LOWPASS = 0;
 
+  @DomName('BiquadFilterNode.LOWSHELF')
+  @DocsEditable
   static const int LOWSHELF = 3;
 
+  @DomName('BiquadFilterNode.NOTCH')
+  @DocsEditable
   static const int NOTCH = 6;
 
+  @DomName('BiquadFilterNode.PEAKING')
+  @DocsEditable
   static const int PEAKING = 5;
 
   @DomName('BiquadFilterNode.Q')
@@ -893,22 +917,40 @@
 class OscillatorNode extends AudioSourceNode {
   OscillatorNode.internal() : super.internal();
 
+  @DomName('OscillatorNode.CUSTOM')
+  @DocsEditable
   static const int CUSTOM = 4;
 
+  @DomName('OscillatorNode.FINISHED_STATE')
+  @DocsEditable
   static const int FINISHED_STATE = 3;
 
+  @DomName('OscillatorNode.PLAYING_STATE')
+  @DocsEditable
   static const int PLAYING_STATE = 2;
 
+  @DomName('OscillatorNode.SAWTOOTH')
+  @DocsEditable
   static const int SAWTOOTH = 2;
 
+  @DomName('OscillatorNode.SCHEDULED_STATE')
+  @DocsEditable
   static const int SCHEDULED_STATE = 1;
 
+  @DomName('OscillatorNode.SINE')
+  @DocsEditable
   static const int SINE = 0;
 
+  @DomName('OscillatorNode.SQUARE')
+  @DocsEditable
   static const int SQUARE = 1;
 
+  @DomName('OscillatorNode.TRIANGLE')
+  @DocsEditable
   static const int TRIANGLE = 3;
 
+  @DomName('OscillatorNode.UNSCHEDULED_STATE')
+  @DocsEditable
   static const int UNSCHEDULED_STATE = 0;
 
   @DomName('OscillatorNode.detune')
@@ -956,16 +998,28 @@
 class PannerNode extends AudioNode {
   PannerNode.internal() : super.internal();
 
+  @DomName('PannerNode.EQUALPOWER')
+  @DocsEditable
   static const int EQUALPOWER = 0;
 
+  @DomName('PannerNode.EXPONENTIAL_DISTANCE')
+  @DocsEditable
   static const int EXPONENTIAL_DISTANCE = 2;
 
+  @DomName('PannerNode.HRTF')
+  @DocsEditable
   static const int HRTF = 1;
 
+  @DomName('PannerNode.INVERSE_DISTANCE')
+  @DocsEditable
   static const int INVERSE_DISTANCE = 1;
 
+  @DomName('PannerNode.LINEAR_DISTANCE')
+  @DocsEditable
   static const int LINEAR_DISTANCE = 0;
 
+  @DomName('PannerNode.SOUNDFIELD')
+  @DocsEditable
   static const int SOUNDFIELD = 2;
 
   @DomName('PannerNode.coneInnerAngle')
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index 2c5f0ee..de46851 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -7,6 +7,7 @@
 import 'dart:typed_data';
 import 'dart:_js_helper' show Creates, JSName, Null, Returns, convertDartClosureToJS;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show Interceptor;
 // DO NOT EDIT - unless you are editing documentation as per:
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:web_gl library.
@@ -355,10 +356,16 @@
 @DomName('WebGLCompressedTextureATC')
 class CompressedTextureAtc native "WebGLCompressedTextureATC" {
 
+  @DomName('WebGLCompressedTextureATC.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL')
+  @DocsEditable
   static const int COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93;
 
+  @DomName('WebGLCompressedTextureATC.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL')
+  @DocsEditable
   static const int COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
 
+  @DomName('WebGLCompressedTextureATC.COMPRESSED_RGB_ATC_WEBGL')
+  @DocsEditable
   static const int COMPRESSED_RGB_ATC_WEBGL = 0x8C92;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -370,12 +377,20 @@
 @DomName('WebGLCompressedTexturePVRTC')
 class CompressedTexturePvrtc native "WebGLCompressedTexturePVRTC" {
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_2BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_4BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -387,12 +402,20 @@
 @DomName('WebGLCompressedTextureS3TC')
 class CompressedTextureS3TC native "WebGLCompressedTextureS3TC" {
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -450,8 +473,12 @@
 @DomName('WebGLDebugRendererInfo')
 class DebugRendererInfo native "WebGLDebugRendererInfo" {
 
+  @DomName('WebGLDebugRendererInfo.UNMASKED_RENDERER_WEBGL')
+  @DocsEditable
   static const int UNMASKED_RENDERER_WEBGL = 0x9246;
 
+  @DomName('WebGLDebugRendererInfo.UNMASKED_VENDOR_WEBGL')
+  @DocsEditable
   static const int UNMASKED_VENDOR_WEBGL = 0x9245;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -476,6 +503,8 @@
 @DomName('WebGLDepthTexture')
 class DepthTexture native "WebGLDepthTexture" {
 
+  @DomName('WebGLDepthTexture.UNSIGNED_INT_24_8_WEBGL')
+  @DocsEditable
   static const int UNSIGNED_INT_24_8_WEBGL = 0x84FA;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -487,72 +516,140 @@
 @DomName('EXTDrawBuffers')
 class ExtDrawBuffers native "EXTDrawBuffers" {
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT0_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT0_EXT = 0x8CE0;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT10_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT10_EXT = 0x8CEA;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT11_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT11_EXT = 0x8CEB;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT12_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT12_EXT = 0x8CEC;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT13_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT13_EXT = 0x8CED;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT14_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT14_EXT = 0x8CEE;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT15_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT15_EXT = 0x8CEF;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT1_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT1_EXT = 0x8CE1;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT2_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT2_EXT = 0x8CE2;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT3_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT3_EXT = 0x8CE3;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT4_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT4_EXT = 0x8CE4;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT5_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT5_EXT = 0x8CE5;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT6_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT6_EXT = 0x8CE6;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT7_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT7_EXT = 0x8CE7;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT8_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT8_EXT = 0x8CE8;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT9_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT9_EXT = 0x8CE9;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER0_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER0_EXT = 0x8825;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER10_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER10_EXT = 0x882F;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER11_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER11_EXT = 0x8830;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER12_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER12_EXT = 0x8831;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER13_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER13_EXT = 0x8832;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER14_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER14_EXT = 0x8833;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER15_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER15_EXT = 0x8834;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER1_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER1_EXT = 0x8826;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER2_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER2_EXT = 0x8827;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER3_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER3_EXT = 0x8828;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER4_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER4_EXT = 0x8829;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER5_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER5_EXT = 0x882A;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER6_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER6_EXT = 0x882B;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER7_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER7_EXT = 0x882C;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER8_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER8_EXT = 0x882D;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER9_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER9_EXT = 0x882E;
 
+  @DomName('EXTDrawBuffers.MAX_COLOR_ATTACHMENTS_EXT')
+  @DocsEditable
   static const int MAX_COLOR_ATTACHMENTS_EXT = 0x8CDF;
 
+  @DomName('EXTDrawBuffers.MAX_DRAW_BUFFERS_EXT')
+  @DocsEditable
   static const int MAX_DRAW_BUFFERS_EXT = 0x8824;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -564,8 +661,12 @@
 @DomName('EXTTextureFilterAnisotropic')
 class ExtTextureFilterAnisotropic native "EXTTextureFilterAnisotropic" {
 
+  @DomName('EXTTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT')
+  @DocsEditable
   static const int MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
 
+  @DomName('EXTTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT')
+  @DocsEditable
   static const int TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -612,6 +713,8 @@
 @DomName('OESStandardDerivatives')
 class OesStandardDerivatives native "OESStandardDerivatives" {
 
+  @DomName('OESStandardDerivatives.FRAGMENT_SHADER_DERIVATIVE_HINT_OES')
+  @DocsEditable
   static const int FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -641,6 +744,8 @@
 @DomName('OESVertexArrayObject')
 class OesVertexArrayObject native "OESVertexArrayObject" {
 
+  @DomName('OESVertexArrayObject.VERTEX_ARRAY_BINDING_OES')
+  @DocsEditable
   static const int VERTEX_ARRAY_BINDING_OES = 0x85B5;
 
   @JSName('bindVertexArrayOES')
@@ -696,596 +801,1188 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => JS('bool', '!!(window.WebGLRenderingContext)');
 
+  @DomName('WebGLRenderingContext.ACTIVE_ATTRIBUTES')
+  @DocsEditable
   static const int ACTIVE_ATTRIBUTES = 0x8B89;
 
+  @DomName('WebGLRenderingContext.ACTIVE_TEXTURE')
+  @DocsEditable
   static const int ACTIVE_TEXTURE = 0x84E0;
 
+  @DomName('WebGLRenderingContext.ACTIVE_UNIFORMS')
+  @DocsEditable
   static const int ACTIVE_UNIFORMS = 0x8B86;
 
+  @DomName('WebGLRenderingContext.ALIASED_LINE_WIDTH_RANGE')
+  @DocsEditable
   static const int ALIASED_LINE_WIDTH_RANGE = 0x846E;
 
+  @DomName('WebGLRenderingContext.ALIASED_POINT_SIZE_RANGE')
+  @DocsEditable
   static const int ALIASED_POINT_SIZE_RANGE = 0x846D;
 
+  @DomName('WebGLRenderingContext.ALPHA')
+  @DocsEditable
   static const int ALPHA = 0x1906;
 
+  @DomName('WebGLRenderingContext.ALPHA_BITS')
+  @DocsEditable
   static const int ALPHA_BITS = 0x0D55;
 
+  @DomName('WebGLRenderingContext.ALWAYS')
+  @DocsEditable
   static const int ALWAYS = 0x0207;
 
+  @DomName('WebGLRenderingContext.ARRAY_BUFFER')
+  @DocsEditable
   static const int ARRAY_BUFFER = 0x8892;
 
+  @DomName('WebGLRenderingContext.ARRAY_BUFFER_BINDING')
+  @DocsEditable
   static const int ARRAY_BUFFER_BINDING = 0x8894;
 
+  @DomName('WebGLRenderingContext.ATTACHED_SHADERS')
+  @DocsEditable
   static const int ATTACHED_SHADERS = 0x8B85;
 
+  @DomName('WebGLRenderingContext.BACK')
+  @DocsEditable
   static const int BACK = 0x0405;
 
+  @DomName('WebGLRenderingContext.BLEND')
+  @DocsEditable
   static const int BLEND = 0x0BE2;
 
+  @DomName('WebGLRenderingContext.BLEND_COLOR')
+  @DocsEditable
   static const int BLEND_COLOR = 0x8005;
 
+  @DomName('WebGLRenderingContext.BLEND_DST_ALPHA')
+  @DocsEditable
   static const int BLEND_DST_ALPHA = 0x80CA;
 
+  @DomName('WebGLRenderingContext.BLEND_DST_RGB')
+  @DocsEditable
   static const int BLEND_DST_RGB = 0x80C8;
 
+  @DomName('WebGLRenderingContext.BLEND_EQUATION')
+  @DocsEditable
   static const int BLEND_EQUATION = 0x8009;
 
+  @DomName('WebGLRenderingContext.BLEND_EQUATION_ALPHA')
+  @DocsEditable
   static const int BLEND_EQUATION_ALPHA = 0x883D;
 
+  @DomName('WebGLRenderingContext.BLEND_EQUATION_RGB')
+  @DocsEditable
   static const int BLEND_EQUATION_RGB = 0x8009;
 
+  @DomName('WebGLRenderingContext.BLEND_SRC_ALPHA')
+  @DocsEditable
   static const int BLEND_SRC_ALPHA = 0x80CB;
 
+  @DomName('WebGLRenderingContext.BLEND_SRC_RGB')
+  @DocsEditable
   static const int BLEND_SRC_RGB = 0x80C9;
 
+  @DomName('WebGLRenderingContext.BLUE_BITS')
+  @DocsEditable
   static const int BLUE_BITS = 0x0D54;
 
+  @DomName('WebGLRenderingContext.BOOL')
+  @DocsEditable
   static const int BOOL = 0x8B56;
 
+  @DomName('WebGLRenderingContext.BOOL_VEC2')
+  @DocsEditable
   static const int BOOL_VEC2 = 0x8B57;
 
+  @DomName('WebGLRenderingContext.BOOL_VEC3')
+  @DocsEditable
   static const int BOOL_VEC3 = 0x8B58;
 
+  @DomName('WebGLRenderingContext.BOOL_VEC4')
+  @DocsEditable
   static const int BOOL_VEC4 = 0x8B59;
 
+  @DomName('WebGLRenderingContext.BROWSER_DEFAULT_WEBGL')
+  @DocsEditable
   static const int BROWSER_DEFAULT_WEBGL = 0x9244;
 
+  @DomName('WebGLRenderingContext.BUFFER_SIZE')
+  @DocsEditable
   static const int BUFFER_SIZE = 0x8764;
 
+  @DomName('WebGLRenderingContext.BUFFER_USAGE')
+  @DocsEditable
   static const int BUFFER_USAGE = 0x8765;
 
+  @DomName('WebGLRenderingContext.BYTE')
+  @DocsEditable
   static const int BYTE = 0x1400;
 
+  @DomName('WebGLRenderingContext.CCW')
+  @DocsEditable
   static const int CCW = 0x0901;
 
+  @DomName('WebGLRenderingContext.CLAMP_TO_EDGE')
+  @DocsEditable
   static const int CLAMP_TO_EDGE = 0x812F;
 
+  @DomName('WebGLRenderingContext.COLOR_ATTACHMENT0')
+  @DocsEditable
   static const int COLOR_ATTACHMENT0 = 0x8CE0;
 
+  @DomName('WebGLRenderingContext.COLOR_BUFFER_BIT')
+  @DocsEditable
   static const int COLOR_BUFFER_BIT = 0x00004000;
 
+  @DomName('WebGLRenderingContext.COLOR_CLEAR_VALUE')
+  @DocsEditable
   static const int COLOR_CLEAR_VALUE = 0x0C22;
 
+  @DomName('WebGLRenderingContext.COLOR_WRITEMASK')
+  @DocsEditable
   static const int COLOR_WRITEMASK = 0x0C23;
 
+  @DomName('WebGLRenderingContext.COMPILE_STATUS')
+  @DocsEditable
   static const int COMPILE_STATUS = 0x8B81;
 
+  @DomName('WebGLRenderingContext.COMPRESSED_TEXTURE_FORMATS')
+  @DocsEditable
   static const int COMPRESSED_TEXTURE_FORMATS = 0x86A3;
 
+  @DomName('WebGLRenderingContext.CONSTANT_ALPHA')
+  @DocsEditable
   static const int CONSTANT_ALPHA = 0x8003;
 
+  @DomName('WebGLRenderingContext.CONSTANT_COLOR')
+  @DocsEditable
   static const int CONSTANT_COLOR = 0x8001;
 
+  @DomName('WebGLRenderingContext.CONTEXT_LOST_WEBGL')
+  @DocsEditable
   static const int CONTEXT_LOST_WEBGL = 0x9242;
 
+  @DomName('WebGLRenderingContext.CULL_FACE')
+  @DocsEditable
   static const int CULL_FACE = 0x0B44;
 
+  @DomName('WebGLRenderingContext.CULL_FACE_MODE')
+  @DocsEditable
   static const int CULL_FACE_MODE = 0x0B45;
 
+  @DomName('WebGLRenderingContext.CURRENT_PROGRAM')
+  @DocsEditable
   static const int CURRENT_PROGRAM = 0x8B8D;
 
+  @DomName('WebGLRenderingContext.CURRENT_VERTEX_ATTRIB')
+  @DocsEditable
   static const int CURRENT_VERTEX_ATTRIB = 0x8626;
 
+  @DomName('WebGLRenderingContext.CW')
+  @DocsEditable
   static const int CW = 0x0900;
 
+  @DomName('WebGLRenderingContext.DECR')
+  @DocsEditable
   static const int DECR = 0x1E03;
 
+  @DomName('WebGLRenderingContext.DECR_WRAP')
+  @DocsEditable
   static const int DECR_WRAP = 0x8508;
 
+  @DomName('WebGLRenderingContext.DELETE_STATUS')
+  @DocsEditable
   static const int DELETE_STATUS = 0x8B80;
 
+  @DomName('WebGLRenderingContext.DEPTH_ATTACHMENT')
+  @DocsEditable
   static const int DEPTH_ATTACHMENT = 0x8D00;
 
+  @DomName('WebGLRenderingContext.DEPTH_BITS')
+  @DocsEditable
   static const int DEPTH_BITS = 0x0D56;
 
+  @DomName('WebGLRenderingContext.DEPTH_BUFFER_BIT')
+  @DocsEditable
   static const int DEPTH_BUFFER_BIT = 0x00000100;
 
+  @DomName('WebGLRenderingContext.DEPTH_CLEAR_VALUE')
+  @DocsEditable
   static const int DEPTH_CLEAR_VALUE = 0x0B73;
 
+  @DomName('WebGLRenderingContext.DEPTH_COMPONENT')
+  @DocsEditable
   static const int DEPTH_COMPONENT = 0x1902;
 
+  @DomName('WebGLRenderingContext.DEPTH_COMPONENT16')
+  @DocsEditable
   static const int DEPTH_COMPONENT16 = 0x81A5;
 
+  @DomName('WebGLRenderingContext.DEPTH_FUNC')
+  @DocsEditable
   static const int DEPTH_FUNC = 0x0B74;
 
+  @DomName('WebGLRenderingContext.DEPTH_RANGE')
+  @DocsEditable
   static const int DEPTH_RANGE = 0x0B70;
 
+  @DomName('WebGLRenderingContext.DEPTH_STENCIL')
+  @DocsEditable
   static const int DEPTH_STENCIL = 0x84F9;
 
+  @DomName('WebGLRenderingContext.DEPTH_STENCIL_ATTACHMENT')
+  @DocsEditable
   static const int DEPTH_STENCIL_ATTACHMENT = 0x821A;
 
+  @DomName('WebGLRenderingContext.DEPTH_TEST')
+  @DocsEditable
   static const int DEPTH_TEST = 0x0B71;
 
+  @DomName('WebGLRenderingContext.DEPTH_WRITEMASK')
+  @DocsEditable
   static const int DEPTH_WRITEMASK = 0x0B72;
 
+  @DomName('WebGLRenderingContext.DITHER')
+  @DocsEditable
   static const int DITHER = 0x0BD0;
 
+  @DomName('WebGLRenderingContext.DONT_CARE')
+  @DocsEditable
   static const int DONT_CARE = 0x1100;
 
+  @DomName('WebGLRenderingContext.DST_ALPHA')
+  @DocsEditable
   static const int DST_ALPHA = 0x0304;
 
+  @DomName('WebGLRenderingContext.DST_COLOR')
+  @DocsEditable
   static const int DST_COLOR = 0x0306;
 
+  @DomName('WebGLRenderingContext.DYNAMIC_DRAW')
+  @DocsEditable
   static const int DYNAMIC_DRAW = 0x88E8;
 
+  @DomName('WebGLRenderingContext.ELEMENT_ARRAY_BUFFER')
+  @DocsEditable
   static const int ELEMENT_ARRAY_BUFFER = 0x8893;
 
+  @DomName('WebGLRenderingContext.ELEMENT_ARRAY_BUFFER_BINDING')
+  @DocsEditable
   static const int ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
 
+  @DomName('WebGLRenderingContext.EQUAL')
+  @DocsEditable
   static const int EQUAL = 0x0202;
 
+  @DomName('WebGLRenderingContext.FASTEST')
+  @DocsEditable
   static const int FASTEST = 0x1101;
 
+  @DomName('WebGLRenderingContext.FLOAT')
+  @DocsEditable
   static const int FLOAT = 0x1406;
 
+  @DomName('WebGLRenderingContext.FLOAT_MAT2')
+  @DocsEditable
   static const int FLOAT_MAT2 = 0x8B5A;
 
+  @DomName('WebGLRenderingContext.FLOAT_MAT3')
+  @DocsEditable
   static const int FLOAT_MAT3 = 0x8B5B;
 
+  @DomName('WebGLRenderingContext.FLOAT_MAT4')
+  @DocsEditable
   static const int FLOAT_MAT4 = 0x8B5C;
 
+  @DomName('WebGLRenderingContext.FLOAT_VEC2')
+  @DocsEditable
   static const int FLOAT_VEC2 = 0x8B50;
 
+  @DomName('WebGLRenderingContext.FLOAT_VEC3')
+  @DocsEditable
   static const int FLOAT_VEC3 = 0x8B51;
 
+  @DomName('WebGLRenderingContext.FLOAT_VEC4')
+  @DocsEditable
   static const int FLOAT_VEC4 = 0x8B52;
 
+  @DomName('WebGLRenderingContext.FRAGMENT_SHADER')
+  @DocsEditable
   static const int FRAGMENT_SHADER = 0x8B30;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER')
+  @DocsEditable
   static const int FRAMEBUFFER = 0x8D40;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_BINDING')
+  @DocsEditable
   static const int FRAMEBUFFER_BINDING = 0x8CA6;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_COMPLETE')
+  @DocsEditable
   static const int FRAMEBUFFER_COMPLETE = 0x8CD5;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_INCOMPLETE_ATTACHMENT')
+  @DocsEditable
   static const int FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_INCOMPLETE_DIMENSIONS')
+  @DocsEditable
   static const int FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT')
+  @DocsEditable
   static const int FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_UNSUPPORTED')
+  @DocsEditable
   static const int FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
 
+  @DomName('WebGLRenderingContext.FRONT')
+  @DocsEditable
   static const int FRONT = 0x0404;
 
+  @DomName('WebGLRenderingContext.FRONT_AND_BACK')
+  @DocsEditable
   static const int FRONT_AND_BACK = 0x0408;
 
+  @DomName('WebGLRenderingContext.FRONT_FACE')
+  @DocsEditable
   static const int FRONT_FACE = 0x0B46;
 
+  @DomName('WebGLRenderingContext.FUNC_ADD')
+  @DocsEditable
   static const int FUNC_ADD = 0x8006;
 
+  @DomName('WebGLRenderingContext.FUNC_REVERSE_SUBTRACT')
+  @DocsEditable
   static const int FUNC_REVERSE_SUBTRACT = 0x800B;
 
+  @DomName('WebGLRenderingContext.FUNC_SUBTRACT')
+  @DocsEditable
   static const int FUNC_SUBTRACT = 0x800A;
 
+  @DomName('WebGLRenderingContext.GENERATE_MIPMAP_HINT')
+  @DocsEditable
   static const int GENERATE_MIPMAP_HINT = 0x8192;
 
+  @DomName('WebGLRenderingContext.GEQUAL')
+  @DocsEditable
   static const int GEQUAL = 0x0206;
 
+  @DomName('WebGLRenderingContext.GREATER')
+  @DocsEditable
   static const int GREATER = 0x0204;
 
+  @DomName('WebGLRenderingContext.GREEN_BITS')
+  @DocsEditable
   static const int GREEN_BITS = 0x0D53;
 
+  @DomName('WebGLRenderingContext.HALF_FLOAT_OES')
+  @DocsEditable
   static const int HALF_FLOAT_OES = 0x8D61;
 
+  @DomName('WebGLRenderingContext.HIGH_FLOAT')
+  @DocsEditable
   static const int HIGH_FLOAT = 0x8DF2;
 
+  @DomName('WebGLRenderingContext.HIGH_INT')
+  @DocsEditable
   static const int HIGH_INT = 0x8DF5;
 
+  @DomName('WebGLRenderingContext.INCR')
+  @DocsEditable
   static const int INCR = 0x1E02;
 
+  @DomName('WebGLRenderingContext.INCR_WRAP')
+  @DocsEditable
   static const int INCR_WRAP = 0x8507;
 
+  @DomName('WebGLRenderingContext.INT')
+  @DocsEditable
   static const int INT = 0x1404;
 
+  @DomName('WebGLRenderingContext.INT_VEC2')
+  @DocsEditable
   static const int INT_VEC2 = 0x8B53;
 
+  @DomName('WebGLRenderingContext.INT_VEC3')
+  @DocsEditable
   static const int INT_VEC3 = 0x8B54;
 
+  @DomName('WebGLRenderingContext.INT_VEC4')
+  @DocsEditable
   static const int INT_VEC4 = 0x8B55;
 
+  @DomName('WebGLRenderingContext.INVALID_ENUM')
+  @DocsEditable
   static const int INVALID_ENUM = 0x0500;
 
+  @DomName('WebGLRenderingContext.INVALID_FRAMEBUFFER_OPERATION')
+  @DocsEditable
   static const int INVALID_FRAMEBUFFER_OPERATION = 0x0506;
 
+  @DomName('WebGLRenderingContext.INVALID_OPERATION')
+  @DocsEditable
   static const int INVALID_OPERATION = 0x0502;
 
+  @DomName('WebGLRenderingContext.INVALID_VALUE')
+  @DocsEditable
   static const int INVALID_VALUE = 0x0501;
 
+  @DomName('WebGLRenderingContext.INVERT')
+  @DocsEditable
   static const int INVERT = 0x150A;
 
+  @DomName('WebGLRenderingContext.KEEP')
+  @DocsEditable
   static const int KEEP = 0x1E00;
 
+  @DomName('WebGLRenderingContext.LEQUAL')
+  @DocsEditable
   static const int LEQUAL = 0x0203;
 
+  @DomName('WebGLRenderingContext.LESS')
+  @DocsEditable
   static const int LESS = 0x0201;
 
+  @DomName('WebGLRenderingContext.LINEAR')
+  @DocsEditable
   static const int LINEAR = 0x2601;
 
+  @DomName('WebGLRenderingContext.LINEAR_MIPMAP_LINEAR')
+  @DocsEditable
   static const int LINEAR_MIPMAP_LINEAR = 0x2703;
 
+  @DomName('WebGLRenderingContext.LINEAR_MIPMAP_NEAREST')
+  @DocsEditable
   static const int LINEAR_MIPMAP_NEAREST = 0x2701;
 
+  @DomName('WebGLRenderingContext.LINES')
+  @DocsEditable
   static const int LINES = 0x0001;
 
+  @DomName('WebGLRenderingContext.LINE_LOOP')
+  @DocsEditable
   static const int LINE_LOOP = 0x0002;
 
+  @DomName('WebGLRenderingContext.LINE_STRIP')
+  @DocsEditable
   static const int LINE_STRIP = 0x0003;
 
+  @DomName('WebGLRenderingContext.LINE_WIDTH')
+  @DocsEditable
   static const int LINE_WIDTH = 0x0B21;
 
+  @DomName('WebGLRenderingContext.LINK_STATUS')
+  @DocsEditable
   static const int LINK_STATUS = 0x8B82;
 
+  @DomName('WebGLRenderingContext.LOW_FLOAT')
+  @DocsEditable
   static const int LOW_FLOAT = 0x8DF0;
 
+  @DomName('WebGLRenderingContext.LOW_INT')
+  @DocsEditable
   static const int LOW_INT = 0x8DF3;
 
+  @DomName('WebGLRenderingContext.LUMINANCE')
+  @DocsEditable
   static const int LUMINANCE = 0x1909;
 
+  @DomName('WebGLRenderingContext.LUMINANCE_ALPHA')
+  @DocsEditable
   static const int LUMINANCE_ALPHA = 0x190A;
 
+  @DomName('WebGLRenderingContext.MAX_COMBINED_TEXTURE_IMAGE_UNITS')
+  @DocsEditable
   static const int MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
 
+  @DomName('WebGLRenderingContext.MAX_CUBE_MAP_TEXTURE_SIZE')
+  @DocsEditable
   static const int MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
 
+  @DomName('WebGLRenderingContext.MAX_FRAGMENT_UNIFORM_VECTORS')
+  @DocsEditable
   static const int MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
 
+  @DomName('WebGLRenderingContext.MAX_RENDERBUFFER_SIZE')
+  @DocsEditable
   static const int MAX_RENDERBUFFER_SIZE = 0x84E8;
 
+  @DomName('WebGLRenderingContext.MAX_TEXTURE_IMAGE_UNITS')
+  @DocsEditable
   static const int MAX_TEXTURE_IMAGE_UNITS = 0x8872;
 
+  @DomName('WebGLRenderingContext.MAX_TEXTURE_SIZE')
+  @DocsEditable
   static const int MAX_TEXTURE_SIZE = 0x0D33;
 
+  @DomName('WebGLRenderingContext.MAX_VARYING_VECTORS')
+  @DocsEditable
   static const int MAX_VARYING_VECTORS = 0x8DFC;
 
+  @DomName('WebGLRenderingContext.MAX_VERTEX_ATTRIBS')
+  @DocsEditable
   static const int MAX_VERTEX_ATTRIBS = 0x8869;
 
+  @DomName('WebGLRenderingContext.MAX_VERTEX_TEXTURE_IMAGE_UNITS')
+  @DocsEditable
   static const int MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
 
+  @DomName('WebGLRenderingContext.MAX_VERTEX_UNIFORM_VECTORS')
+  @DocsEditable
   static const int MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
 
+  @DomName('WebGLRenderingContext.MAX_VIEWPORT_DIMS')
+  @DocsEditable
   static const int MAX_VIEWPORT_DIMS = 0x0D3A;
 
+  @DomName('WebGLRenderingContext.MEDIUM_FLOAT')
+  @DocsEditable
   static const int MEDIUM_FLOAT = 0x8DF1;
 
+  @DomName('WebGLRenderingContext.MEDIUM_INT')
+  @DocsEditable
   static const int MEDIUM_INT = 0x8DF4;
 
+  @DomName('WebGLRenderingContext.MIRRORED_REPEAT')
+  @DocsEditable
   static const int MIRRORED_REPEAT = 0x8370;
 
+  @DomName('WebGLRenderingContext.NEAREST')
+  @DocsEditable
   static const int NEAREST = 0x2600;
 
+  @DomName('WebGLRenderingContext.NEAREST_MIPMAP_LINEAR')
+  @DocsEditable
   static const int NEAREST_MIPMAP_LINEAR = 0x2702;
 
+  @DomName('WebGLRenderingContext.NEAREST_MIPMAP_NEAREST')
+  @DocsEditable
   static const int NEAREST_MIPMAP_NEAREST = 0x2700;
 
+  @DomName('WebGLRenderingContext.NEVER')
+  @DocsEditable
   static const int NEVER = 0x0200;
 
+  @DomName('WebGLRenderingContext.NICEST')
+  @DocsEditable
   static const int NICEST = 0x1102;
 
+  @DomName('WebGLRenderingContext.NONE')
+  @DocsEditable
   static const int NONE = 0;
 
+  @DomName('WebGLRenderingContext.NOTEQUAL')
+  @DocsEditable
   static const int NOTEQUAL = 0x0205;
 
+  @DomName('WebGLRenderingContext.NO_ERROR')
+  @DocsEditable
   static const int NO_ERROR = 0;
 
+  @DomName('WebGLRenderingContext.ONE')
+  @DocsEditable
   static const int ONE = 1;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_CONSTANT_ALPHA')
+  @DocsEditable
   static const int ONE_MINUS_CONSTANT_ALPHA = 0x8004;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_CONSTANT_COLOR')
+  @DocsEditable
   static const int ONE_MINUS_CONSTANT_COLOR = 0x8002;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_DST_ALPHA')
+  @DocsEditable
   static const int ONE_MINUS_DST_ALPHA = 0x0305;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_DST_COLOR')
+  @DocsEditable
   static const int ONE_MINUS_DST_COLOR = 0x0307;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_SRC_ALPHA')
+  @DocsEditable
   static const int ONE_MINUS_SRC_ALPHA = 0x0303;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_SRC_COLOR')
+  @DocsEditable
   static const int ONE_MINUS_SRC_COLOR = 0x0301;
 
+  @DomName('WebGLRenderingContext.OUT_OF_MEMORY')
+  @DocsEditable
   static const int OUT_OF_MEMORY = 0x0505;
 
+  @DomName('WebGLRenderingContext.PACK_ALIGNMENT')
+  @DocsEditable
   static const int PACK_ALIGNMENT = 0x0D05;
 
+  @DomName('WebGLRenderingContext.POINTS')
+  @DocsEditable
   static const int POINTS = 0x0000;
 
+  @DomName('WebGLRenderingContext.POLYGON_OFFSET_FACTOR')
+  @DocsEditable
   static const int POLYGON_OFFSET_FACTOR = 0x8038;
 
+  @DomName('WebGLRenderingContext.POLYGON_OFFSET_FILL')
+  @DocsEditable
   static const int POLYGON_OFFSET_FILL = 0x8037;
 
+  @DomName('WebGLRenderingContext.POLYGON_OFFSET_UNITS')
+  @DocsEditable
   static const int POLYGON_OFFSET_UNITS = 0x2A00;
 
+  @DomName('WebGLRenderingContext.RED_BITS')
+  @DocsEditable
   static const int RED_BITS = 0x0D52;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER')
+  @DocsEditable
   static const int RENDERBUFFER = 0x8D41;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_ALPHA_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_ALPHA_SIZE = 0x8D53;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_BINDING')
+  @DocsEditable
   static const int RENDERBUFFER_BINDING = 0x8CA7;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_BLUE_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_BLUE_SIZE = 0x8D52;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_DEPTH_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_DEPTH_SIZE = 0x8D54;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_GREEN_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_GREEN_SIZE = 0x8D51;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_HEIGHT')
+  @DocsEditable
   static const int RENDERBUFFER_HEIGHT = 0x8D43;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_INTERNAL_FORMAT')
+  @DocsEditable
   static const int RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_RED_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_RED_SIZE = 0x8D50;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_STENCIL_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_STENCIL_SIZE = 0x8D55;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_WIDTH')
+  @DocsEditable
   static const int RENDERBUFFER_WIDTH = 0x8D42;
 
+  @DomName('WebGLRenderingContext.RENDERER')
+  @DocsEditable
   static const int RENDERER = 0x1F01;
 
+  @DomName('WebGLRenderingContext.REPEAT')
+  @DocsEditable
   static const int REPEAT = 0x2901;
 
+  @DomName('WebGLRenderingContext.REPLACE')
+  @DocsEditable
   static const int REPLACE = 0x1E01;
 
+  @DomName('WebGLRenderingContext.RGB')
+  @DocsEditable
   static const int RGB = 0x1907;
 
+  @DomName('WebGLRenderingContext.RGB565')
+  @DocsEditable
   static const int RGB565 = 0x8D62;
 
+  @DomName('WebGLRenderingContext.RGB5_A1')
+  @DocsEditable
   static const int RGB5_A1 = 0x8057;
 
+  @DomName('WebGLRenderingContext.RGBA')
+  @DocsEditable
   static const int RGBA = 0x1908;
 
+  @DomName('WebGLRenderingContext.RGBA4')
+  @DocsEditable
   static const int RGBA4 = 0x8056;
 
+  @DomName('WebGLRenderingContext.SAMPLER_2D')
+  @DocsEditable
   static const int SAMPLER_2D = 0x8B5E;
 
+  @DomName('WebGLRenderingContext.SAMPLER_CUBE')
+  @DocsEditable
   static const int SAMPLER_CUBE = 0x8B60;
 
+  @DomName('WebGLRenderingContext.SAMPLES')
+  @DocsEditable
   static const int SAMPLES = 0x80A9;
 
+  @DomName('WebGLRenderingContext.SAMPLE_ALPHA_TO_COVERAGE')
+  @DocsEditable
   static const int SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
 
+  @DomName('WebGLRenderingContext.SAMPLE_BUFFERS')
+  @DocsEditable
   static const int SAMPLE_BUFFERS = 0x80A8;
 
+  @DomName('WebGLRenderingContext.SAMPLE_COVERAGE')
+  @DocsEditable
   static const int SAMPLE_COVERAGE = 0x80A0;
 
+  @DomName('WebGLRenderingContext.SAMPLE_COVERAGE_INVERT')
+  @DocsEditable
   static const int SAMPLE_COVERAGE_INVERT = 0x80AB;
 
+  @DomName('WebGLRenderingContext.SAMPLE_COVERAGE_VALUE')
+  @DocsEditable
   static const int SAMPLE_COVERAGE_VALUE = 0x80AA;
 
+  @DomName('WebGLRenderingContext.SCISSOR_BOX')
+  @DocsEditable
   static const int SCISSOR_BOX = 0x0C10;
 
+  @DomName('WebGLRenderingContext.SCISSOR_TEST')
+  @DocsEditable
   static const int SCISSOR_TEST = 0x0C11;
 
+  @DomName('WebGLRenderingContext.SHADER_TYPE')
+  @DocsEditable
   static const int SHADER_TYPE = 0x8B4F;
 
+  @DomName('WebGLRenderingContext.SHADING_LANGUAGE_VERSION')
+  @DocsEditable
   static const int SHADING_LANGUAGE_VERSION = 0x8B8C;
 
+  @DomName('WebGLRenderingContext.SHORT')
+  @DocsEditable
   static const int SHORT = 0x1402;
 
+  @DomName('WebGLRenderingContext.SRC_ALPHA')
+  @DocsEditable
   static const int SRC_ALPHA = 0x0302;
 
+  @DomName('WebGLRenderingContext.SRC_ALPHA_SATURATE')
+  @DocsEditable
   static const int SRC_ALPHA_SATURATE = 0x0308;
 
+  @DomName('WebGLRenderingContext.SRC_COLOR')
+  @DocsEditable
   static const int SRC_COLOR = 0x0300;
 
+  @DomName('WebGLRenderingContext.STATIC_DRAW')
+  @DocsEditable
   static const int STATIC_DRAW = 0x88E4;
 
+  @DomName('WebGLRenderingContext.STENCIL_ATTACHMENT')
+  @DocsEditable
   static const int STENCIL_ATTACHMENT = 0x8D20;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_FAIL')
+  @DocsEditable
   static const int STENCIL_BACK_FAIL = 0x8801;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_FUNC')
+  @DocsEditable
   static const int STENCIL_BACK_FUNC = 0x8800;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_PASS_DEPTH_FAIL')
+  @DocsEditable
   static const int STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_PASS_DEPTH_PASS')
+  @DocsEditable
   static const int STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_REF')
+  @DocsEditable
   static const int STENCIL_BACK_REF = 0x8CA3;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_VALUE_MASK')
+  @DocsEditable
   static const int STENCIL_BACK_VALUE_MASK = 0x8CA4;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_WRITEMASK')
+  @DocsEditable
   static const int STENCIL_BACK_WRITEMASK = 0x8CA5;
 
+  @DomName('WebGLRenderingContext.STENCIL_BITS')
+  @DocsEditable
   static const int STENCIL_BITS = 0x0D57;
 
+  @DomName('WebGLRenderingContext.STENCIL_BUFFER_BIT')
+  @DocsEditable
   static const int STENCIL_BUFFER_BIT = 0x00000400;
 
+  @DomName('WebGLRenderingContext.STENCIL_CLEAR_VALUE')
+  @DocsEditable
   static const int STENCIL_CLEAR_VALUE = 0x0B91;
 
+  @DomName('WebGLRenderingContext.STENCIL_FAIL')
+  @DocsEditable
   static const int STENCIL_FAIL = 0x0B94;
 
+  @DomName('WebGLRenderingContext.STENCIL_FUNC')
+  @DocsEditable
   static const int STENCIL_FUNC = 0x0B92;
 
+  @DomName('WebGLRenderingContext.STENCIL_INDEX')
+  @DocsEditable
   static const int STENCIL_INDEX = 0x1901;
 
+  @DomName('WebGLRenderingContext.STENCIL_INDEX8')
+  @DocsEditable
   static const int STENCIL_INDEX8 = 0x8D48;
 
+  @DomName('WebGLRenderingContext.STENCIL_PASS_DEPTH_FAIL')
+  @DocsEditable
   static const int STENCIL_PASS_DEPTH_FAIL = 0x0B95;
 
+  @DomName('WebGLRenderingContext.STENCIL_PASS_DEPTH_PASS')
+  @DocsEditable
   static const int STENCIL_PASS_DEPTH_PASS = 0x0B96;
 
+  @DomName('WebGLRenderingContext.STENCIL_REF')
+  @DocsEditable
   static const int STENCIL_REF = 0x0B97;
 
+  @DomName('WebGLRenderingContext.STENCIL_TEST')
+  @DocsEditable
   static const int STENCIL_TEST = 0x0B90;
 
+  @DomName('WebGLRenderingContext.STENCIL_VALUE_MASK')
+  @DocsEditable
   static const int STENCIL_VALUE_MASK = 0x0B93;
 
+  @DomName('WebGLRenderingContext.STENCIL_WRITEMASK')
+  @DocsEditable
   static const int STENCIL_WRITEMASK = 0x0B98;
 
+  @DomName('WebGLRenderingContext.STREAM_DRAW')
+  @DocsEditable
   static const int STREAM_DRAW = 0x88E0;
 
+  @DomName('WebGLRenderingContext.SUBPIXEL_BITS')
+  @DocsEditable
   static const int SUBPIXEL_BITS = 0x0D50;
 
+  @DomName('WebGLRenderingContext.TEXTURE')
+  @DocsEditable
   static const int TEXTURE = 0x1702;
 
+  @DomName('WebGLRenderingContext.TEXTURE0')
+  @DocsEditable
   static const int TEXTURE0 = 0x84C0;
 
+  @DomName('WebGLRenderingContext.TEXTURE1')
+  @DocsEditable
   static const int TEXTURE1 = 0x84C1;
 
+  @DomName('WebGLRenderingContext.TEXTURE10')
+  @DocsEditable
   static const int TEXTURE10 = 0x84CA;
 
+  @DomName('WebGLRenderingContext.TEXTURE11')
+  @DocsEditable
   static const int TEXTURE11 = 0x84CB;
 
+  @DomName('WebGLRenderingContext.TEXTURE12')
+  @DocsEditable
   static const int TEXTURE12 = 0x84CC;
 
+  @DomName('WebGLRenderingContext.TEXTURE13')
+  @DocsEditable
   static const int TEXTURE13 = 0x84CD;
 
+  @DomName('WebGLRenderingContext.TEXTURE14')
+  @DocsEditable
   static const int TEXTURE14 = 0x84CE;
 
+  @DomName('WebGLRenderingContext.TEXTURE15')
+  @DocsEditable
   static const int TEXTURE15 = 0x84CF;
 
+  @DomName('WebGLRenderingContext.TEXTURE16')
+  @DocsEditable
   static const int TEXTURE16 = 0x84D0;
 
+  @DomName('WebGLRenderingContext.TEXTURE17')
+  @DocsEditable
   static const int TEXTURE17 = 0x84D1;
 
+  @DomName('WebGLRenderingContext.TEXTURE18')
+  @DocsEditable
   static const int TEXTURE18 = 0x84D2;
 
+  @DomName('WebGLRenderingContext.TEXTURE19')
+  @DocsEditable
   static const int TEXTURE19 = 0x84D3;
 
+  @DomName('WebGLRenderingContext.TEXTURE2')
+  @DocsEditable
   static const int TEXTURE2 = 0x84C2;
 
+  @DomName('WebGLRenderingContext.TEXTURE20')
+  @DocsEditable
   static const int TEXTURE20 = 0x84D4;
 
+  @DomName('WebGLRenderingContext.TEXTURE21')
+  @DocsEditable
   static const int TEXTURE21 = 0x84D5;
 
+  @DomName('WebGLRenderingContext.TEXTURE22')
+  @DocsEditable
   static const int TEXTURE22 = 0x84D6;
 
+  @DomName('WebGLRenderingContext.TEXTURE23')
+  @DocsEditable
   static const int TEXTURE23 = 0x84D7;
 
+  @DomName('WebGLRenderingContext.TEXTURE24')
+  @DocsEditable
   static const int TEXTURE24 = 0x84D8;
 
+  @DomName('WebGLRenderingContext.TEXTURE25')
+  @DocsEditable
   static const int TEXTURE25 = 0x84D9;
 
+  @DomName('WebGLRenderingContext.TEXTURE26')
+  @DocsEditable
   static const int TEXTURE26 = 0x84DA;
 
+  @DomName('WebGLRenderingContext.TEXTURE27')
+  @DocsEditable
   static const int TEXTURE27 = 0x84DB;
 
+  @DomName('WebGLRenderingContext.TEXTURE28')
+  @DocsEditable
   static const int TEXTURE28 = 0x84DC;
 
+  @DomName('WebGLRenderingContext.TEXTURE29')
+  @DocsEditable
   static const int TEXTURE29 = 0x84DD;
 
+  @DomName('WebGLRenderingContext.TEXTURE3')
+  @DocsEditable
   static const int TEXTURE3 = 0x84C3;
 
+  @DomName('WebGLRenderingContext.TEXTURE30')
+  @DocsEditable
   static const int TEXTURE30 = 0x84DE;
 
+  @DomName('WebGLRenderingContext.TEXTURE31')
+  @DocsEditable
   static const int TEXTURE31 = 0x84DF;
 
+  @DomName('WebGLRenderingContext.TEXTURE4')
+  @DocsEditable
   static const int TEXTURE4 = 0x84C4;
 
+  @DomName('WebGLRenderingContext.TEXTURE5')
+  @DocsEditable
   static const int TEXTURE5 = 0x84C5;
 
+  @DomName('WebGLRenderingContext.TEXTURE6')
+  @DocsEditable
   static const int TEXTURE6 = 0x84C6;
 
+  @DomName('WebGLRenderingContext.TEXTURE7')
+  @DocsEditable
   static const int TEXTURE7 = 0x84C7;
 
+  @DomName('WebGLRenderingContext.TEXTURE8')
+  @DocsEditable
   static const int TEXTURE8 = 0x84C8;
 
+  @DomName('WebGLRenderingContext.TEXTURE9')
+  @DocsEditable
   static const int TEXTURE9 = 0x84C9;
 
+  @DomName('WebGLRenderingContext.TEXTURE_2D')
+  @DocsEditable
   static const int TEXTURE_2D = 0x0DE1;
 
+  @DomName('WebGLRenderingContext.TEXTURE_BINDING_2D')
+  @DocsEditable
   static const int TEXTURE_BINDING_2D = 0x8069;
 
+  @DomName('WebGLRenderingContext.TEXTURE_BINDING_CUBE_MAP')
+  @DocsEditable
   static const int TEXTURE_BINDING_CUBE_MAP = 0x8514;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP = 0x8513;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_X')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Y')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Z')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_X')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Y')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Z')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
 
+  @DomName('WebGLRenderingContext.TEXTURE_MAG_FILTER')
+  @DocsEditable
   static const int TEXTURE_MAG_FILTER = 0x2800;
 
+  @DomName('WebGLRenderingContext.TEXTURE_MIN_FILTER')
+  @DocsEditable
   static const int TEXTURE_MIN_FILTER = 0x2801;
 
+  @DomName('WebGLRenderingContext.TEXTURE_WRAP_S')
+  @DocsEditable
   static const int TEXTURE_WRAP_S = 0x2802;
 
+  @DomName('WebGLRenderingContext.TEXTURE_WRAP_T')
+  @DocsEditable
   static const int TEXTURE_WRAP_T = 0x2803;
 
+  @DomName('WebGLRenderingContext.TRIANGLES')
+  @DocsEditable
   static const int TRIANGLES = 0x0004;
 
+  @DomName('WebGLRenderingContext.TRIANGLE_FAN')
+  @DocsEditable
   static const int TRIANGLE_FAN = 0x0006;
 
+  @DomName('WebGLRenderingContext.TRIANGLE_STRIP')
+  @DocsEditable
   static const int TRIANGLE_STRIP = 0x0005;
 
+  @DomName('WebGLRenderingContext.UNPACK_ALIGNMENT')
+  @DocsEditable
   static const int UNPACK_ALIGNMENT = 0x0CF5;
 
+  @DomName('WebGLRenderingContext.UNPACK_COLORSPACE_CONVERSION_WEBGL')
+  @DocsEditable
   static const int UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
 
+  @DomName('WebGLRenderingContext.UNPACK_FLIP_Y_WEBGL')
+  @DocsEditable
   static const int UNPACK_FLIP_Y_WEBGL = 0x9240;
 
+  @DomName('WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL')
+  @DocsEditable
   static const int UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_BYTE')
+  @DocsEditable
   static const int UNSIGNED_BYTE = 0x1401;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_INT')
+  @DocsEditable
   static const int UNSIGNED_INT = 0x1405;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT')
+  @DocsEditable
   static const int UNSIGNED_SHORT = 0x1403;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT_4_4_4_4')
+  @DocsEditable
   static const int UNSIGNED_SHORT_4_4_4_4 = 0x8033;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT_5_5_5_1')
+  @DocsEditable
   static const int UNSIGNED_SHORT_5_5_5_1 = 0x8034;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT_5_6_5')
+  @DocsEditable
   static const int UNSIGNED_SHORT_5_6_5 = 0x8363;
 
+  @DomName('WebGLRenderingContext.VALIDATE_STATUS')
+  @DocsEditable
   static const int VALIDATE_STATUS = 0x8B83;
 
+  @DomName('WebGLRenderingContext.VENDOR')
+  @DocsEditable
   static const int VENDOR = 0x1F00;
 
+  @DomName('WebGLRenderingContext.VERSION')
+  @DocsEditable
   static const int VERSION = 0x1F02;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_ENABLED')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_NORMALIZED')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_POINTER')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_SIZE')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_STRIDE')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_TYPE')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
 
+  @DomName('WebGLRenderingContext.VERTEX_SHADER')
+  @DocsEditable
   static const int VERTEX_SHADER = 0x8B31;
 
+  @DomName('WebGLRenderingContext.VIEWPORT')
+  @DocsEditable
   static const int VIEWPORT = 0x0BA2;
 
+  @DomName('WebGLRenderingContext.ZERO')
+  @DocsEditable
   static const int ZERO = 0;
 
   @DomName('WebGLRenderingContext.drawingBufferHeight')
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index 7287b8f..31db381 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -365,10 +365,16 @@
 class CompressedTextureAtc extends NativeFieldWrapperClass1 {
   CompressedTextureAtc.internal();
 
+  @DomName('WebGLCompressedTextureATC.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL')
+  @DocsEditable
   static const int COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93;
 
+  @DomName('WebGLCompressedTextureATC.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL')
+  @DocsEditable
   static const int COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
 
+  @DomName('WebGLCompressedTextureATC.COMPRESSED_RGB_ATC_WEBGL')
+  @DocsEditable
   static const int COMPRESSED_RGB_ATC_WEBGL = 0x8C92;
 
 }
@@ -384,12 +390,20 @@
 class CompressedTexturePvrtc extends NativeFieldWrapperClass1 {
   CompressedTexturePvrtc.internal();
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_2BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
 
+  @DomName('WebGLCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_4BPPV1_IMG')
+  @DocsEditable
   static const int COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
 
 }
@@ -405,12 +419,20 @@
 class CompressedTextureS3TC extends NativeFieldWrapperClass1 {
   CompressedTextureS3TC.internal();
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
 
+  @DomName('WebGLCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT')
+  @DocsEditable
   static const int COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
 
 }
@@ -504,8 +526,12 @@
 class DebugRendererInfo extends NativeFieldWrapperClass1 {
   DebugRendererInfo.internal();
 
+  @DomName('WebGLDebugRendererInfo.UNMASKED_RENDERER_WEBGL')
+  @DocsEditable
   static const int UNMASKED_RENDERER_WEBGL = 0x9246;
 
+  @DomName('WebGLDebugRendererInfo.UNMASKED_VENDOR_WEBGL')
+  @DocsEditable
   static const int UNMASKED_VENDOR_WEBGL = 0x9245;
 
 }
@@ -538,6 +564,8 @@
 class DepthTexture extends NativeFieldWrapperClass1 {
   DepthTexture.internal();
 
+  @DomName('WebGLDepthTexture.UNSIGNED_INT_24_8_WEBGL')
+  @DocsEditable
   static const int UNSIGNED_INT_24_8_WEBGL = 0x84FA;
 
 }
@@ -553,72 +581,140 @@
 class ExtDrawBuffers extends NativeFieldWrapperClass1 {
   ExtDrawBuffers.internal();
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT0_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT0_EXT = 0x8CE0;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT10_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT10_EXT = 0x8CEA;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT11_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT11_EXT = 0x8CEB;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT12_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT12_EXT = 0x8CEC;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT13_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT13_EXT = 0x8CED;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT14_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT14_EXT = 0x8CEE;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT15_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT15_EXT = 0x8CEF;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT1_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT1_EXT = 0x8CE1;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT2_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT2_EXT = 0x8CE2;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT3_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT3_EXT = 0x8CE3;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT4_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT4_EXT = 0x8CE4;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT5_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT5_EXT = 0x8CE5;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT6_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT6_EXT = 0x8CE6;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT7_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT7_EXT = 0x8CE7;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT8_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT8_EXT = 0x8CE8;
 
+  @DomName('EXTDrawBuffers.COLOR_ATTACHMENT9_EXT')
+  @DocsEditable
   static const int COLOR_ATTACHMENT9_EXT = 0x8CE9;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER0_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER0_EXT = 0x8825;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER10_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER10_EXT = 0x882F;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER11_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER11_EXT = 0x8830;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER12_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER12_EXT = 0x8831;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER13_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER13_EXT = 0x8832;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER14_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER14_EXT = 0x8833;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER15_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER15_EXT = 0x8834;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER1_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER1_EXT = 0x8826;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER2_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER2_EXT = 0x8827;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER3_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER3_EXT = 0x8828;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER4_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER4_EXT = 0x8829;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER5_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER5_EXT = 0x882A;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER6_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER6_EXT = 0x882B;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER7_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER7_EXT = 0x882C;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER8_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER8_EXT = 0x882D;
 
+  @DomName('EXTDrawBuffers.DRAW_BUFFER9_EXT')
+  @DocsEditable
   static const int DRAW_BUFFER9_EXT = 0x882E;
 
+  @DomName('EXTDrawBuffers.MAX_COLOR_ATTACHMENTS_EXT')
+  @DocsEditable
   static const int MAX_COLOR_ATTACHMENTS_EXT = 0x8CDF;
 
+  @DomName('EXTDrawBuffers.MAX_DRAW_BUFFERS_EXT')
+  @DocsEditable
   static const int MAX_DRAW_BUFFERS_EXT = 0x8824;
 
 }
@@ -634,8 +730,12 @@
 class ExtTextureFilterAnisotropic extends NativeFieldWrapperClass1 {
   ExtTextureFilterAnisotropic.internal();
 
+  @DomName('EXTTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT')
+  @DocsEditable
   static const int MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
 
+  @DomName('EXTTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT')
+  @DocsEditable
   static const int TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
 
 }
@@ -698,6 +798,8 @@
 class OesStandardDerivatives extends NativeFieldWrapperClass1 {
   OesStandardDerivatives.internal();
 
+  @DomName('OESStandardDerivatives.FRAGMENT_SHADER_DERIVATIVE_HINT_OES')
+  @DocsEditable
   static const int FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
 
 }
@@ -739,6 +841,8 @@
 class OesVertexArrayObject extends NativeFieldWrapperClass1 {
   OesVertexArrayObject.internal();
 
+  @DomName('OESVertexArrayObject.VERTEX_ARRAY_BINDING_OES')
+  @DocsEditable
   static const int VERTEX_ARRAY_BINDING_OES = 0x85B5;
 
   @DomName('OESVertexArrayObject.bindVertexArrayOES')
@@ -802,596 +906,1188 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
+  @DomName('WebGLRenderingContext.ACTIVE_ATTRIBUTES')
+  @DocsEditable
   static const int ACTIVE_ATTRIBUTES = 0x8B89;
 
+  @DomName('WebGLRenderingContext.ACTIVE_TEXTURE')
+  @DocsEditable
   static const int ACTIVE_TEXTURE = 0x84E0;
 
+  @DomName('WebGLRenderingContext.ACTIVE_UNIFORMS')
+  @DocsEditable
   static const int ACTIVE_UNIFORMS = 0x8B86;
 
+  @DomName('WebGLRenderingContext.ALIASED_LINE_WIDTH_RANGE')
+  @DocsEditable
   static const int ALIASED_LINE_WIDTH_RANGE = 0x846E;
 
+  @DomName('WebGLRenderingContext.ALIASED_POINT_SIZE_RANGE')
+  @DocsEditable
   static const int ALIASED_POINT_SIZE_RANGE = 0x846D;
 
+  @DomName('WebGLRenderingContext.ALPHA')
+  @DocsEditable
   static const int ALPHA = 0x1906;
 
+  @DomName('WebGLRenderingContext.ALPHA_BITS')
+  @DocsEditable
   static const int ALPHA_BITS = 0x0D55;
 
+  @DomName('WebGLRenderingContext.ALWAYS')
+  @DocsEditable
   static const int ALWAYS = 0x0207;
 
+  @DomName('WebGLRenderingContext.ARRAY_BUFFER')
+  @DocsEditable
   static const int ARRAY_BUFFER = 0x8892;
 
+  @DomName('WebGLRenderingContext.ARRAY_BUFFER_BINDING')
+  @DocsEditable
   static const int ARRAY_BUFFER_BINDING = 0x8894;
 
+  @DomName('WebGLRenderingContext.ATTACHED_SHADERS')
+  @DocsEditable
   static const int ATTACHED_SHADERS = 0x8B85;
 
+  @DomName('WebGLRenderingContext.BACK')
+  @DocsEditable
   static const int BACK = 0x0405;
 
+  @DomName('WebGLRenderingContext.BLEND')
+  @DocsEditable
   static const int BLEND = 0x0BE2;
 
+  @DomName('WebGLRenderingContext.BLEND_COLOR')
+  @DocsEditable
   static const int BLEND_COLOR = 0x8005;
 
+  @DomName('WebGLRenderingContext.BLEND_DST_ALPHA')
+  @DocsEditable
   static const int BLEND_DST_ALPHA = 0x80CA;
 
+  @DomName('WebGLRenderingContext.BLEND_DST_RGB')
+  @DocsEditable
   static const int BLEND_DST_RGB = 0x80C8;
 
+  @DomName('WebGLRenderingContext.BLEND_EQUATION')
+  @DocsEditable
   static const int BLEND_EQUATION = 0x8009;
 
+  @DomName('WebGLRenderingContext.BLEND_EQUATION_ALPHA')
+  @DocsEditable
   static const int BLEND_EQUATION_ALPHA = 0x883D;
 
+  @DomName('WebGLRenderingContext.BLEND_EQUATION_RGB')
+  @DocsEditable
   static const int BLEND_EQUATION_RGB = 0x8009;
 
+  @DomName('WebGLRenderingContext.BLEND_SRC_ALPHA')
+  @DocsEditable
   static const int BLEND_SRC_ALPHA = 0x80CB;
 
+  @DomName('WebGLRenderingContext.BLEND_SRC_RGB')
+  @DocsEditable
   static const int BLEND_SRC_RGB = 0x80C9;
 
+  @DomName('WebGLRenderingContext.BLUE_BITS')
+  @DocsEditable
   static const int BLUE_BITS = 0x0D54;
 
+  @DomName('WebGLRenderingContext.BOOL')
+  @DocsEditable
   static const int BOOL = 0x8B56;
 
+  @DomName('WebGLRenderingContext.BOOL_VEC2')
+  @DocsEditable
   static const int BOOL_VEC2 = 0x8B57;
 
+  @DomName('WebGLRenderingContext.BOOL_VEC3')
+  @DocsEditable
   static const int BOOL_VEC3 = 0x8B58;
 
+  @DomName('WebGLRenderingContext.BOOL_VEC4')
+  @DocsEditable
   static const int BOOL_VEC4 = 0x8B59;
 
+  @DomName('WebGLRenderingContext.BROWSER_DEFAULT_WEBGL')
+  @DocsEditable
   static const int BROWSER_DEFAULT_WEBGL = 0x9244;
 
+  @DomName('WebGLRenderingContext.BUFFER_SIZE')
+  @DocsEditable
   static const int BUFFER_SIZE = 0x8764;
 
+  @DomName('WebGLRenderingContext.BUFFER_USAGE')
+  @DocsEditable
   static const int BUFFER_USAGE = 0x8765;
 
+  @DomName('WebGLRenderingContext.BYTE')
+  @DocsEditable
   static const int BYTE = 0x1400;
 
+  @DomName('WebGLRenderingContext.CCW')
+  @DocsEditable
   static const int CCW = 0x0901;
 
+  @DomName('WebGLRenderingContext.CLAMP_TO_EDGE')
+  @DocsEditable
   static const int CLAMP_TO_EDGE = 0x812F;
 
+  @DomName('WebGLRenderingContext.COLOR_ATTACHMENT0')
+  @DocsEditable
   static const int COLOR_ATTACHMENT0 = 0x8CE0;
 
+  @DomName('WebGLRenderingContext.COLOR_BUFFER_BIT')
+  @DocsEditable
   static const int COLOR_BUFFER_BIT = 0x00004000;
 
+  @DomName('WebGLRenderingContext.COLOR_CLEAR_VALUE')
+  @DocsEditable
   static const int COLOR_CLEAR_VALUE = 0x0C22;
 
+  @DomName('WebGLRenderingContext.COLOR_WRITEMASK')
+  @DocsEditable
   static const int COLOR_WRITEMASK = 0x0C23;
 
+  @DomName('WebGLRenderingContext.COMPILE_STATUS')
+  @DocsEditable
   static const int COMPILE_STATUS = 0x8B81;
 
+  @DomName('WebGLRenderingContext.COMPRESSED_TEXTURE_FORMATS')
+  @DocsEditable
   static const int COMPRESSED_TEXTURE_FORMATS = 0x86A3;
 
+  @DomName('WebGLRenderingContext.CONSTANT_ALPHA')
+  @DocsEditable
   static const int CONSTANT_ALPHA = 0x8003;
 
+  @DomName('WebGLRenderingContext.CONSTANT_COLOR')
+  @DocsEditable
   static const int CONSTANT_COLOR = 0x8001;
 
+  @DomName('WebGLRenderingContext.CONTEXT_LOST_WEBGL')
+  @DocsEditable
   static const int CONTEXT_LOST_WEBGL = 0x9242;
 
+  @DomName('WebGLRenderingContext.CULL_FACE')
+  @DocsEditable
   static const int CULL_FACE = 0x0B44;
 
+  @DomName('WebGLRenderingContext.CULL_FACE_MODE')
+  @DocsEditable
   static const int CULL_FACE_MODE = 0x0B45;
 
+  @DomName('WebGLRenderingContext.CURRENT_PROGRAM')
+  @DocsEditable
   static const int CURRENT_PROGRAM = 0x8B8D;
 
+  @DomName('WebGLRenderingContext.CURRENT_VERTEX_ATTRIB')
+  @DocsEditable
   static const int CURRENT_VERTEX_ATTRIB = 0x8626;
 
+  @DomName('WebGLRenderingContext.CW')
+  @DocsEditable
   static const int CW = 0x0900;
 
+  @DomName('WebGLRenderingContext.DECR')
+  @DocsEditable
   static const int DECR = 0x1E03;
 
+  @DomName('WebGLRenderingContext.DECR_WRAP')
+  @DocsEditable
   static const int DECR_WRAP = 0x8508;
 
+  @DomName('WebGLRenderingContext.DELETE_STATUS')
+  @DocsEditable
   static const int DELETE_STATUS = 0x8B80;
 
+  @DomName('WebGLRenderingContext.DEPTH_ATTACHMENT')
+  @DocsEditable
   static const int DEPTH_ATTACHMENT = 0x8D00;
 
+  @DomName('WebGLRenderingContext.DEPTH_BITS')
+  @DocsEditable
   static const int DEPTH_BITS = 0x0D56;
 
+  @DomName('WebGLRenderingContext.DEPTH_BUFFER_BIT')
+  @DocsEditable
   static const int DEPTH_BUFFER_BIT = 0x00000100;
 
+  @DomName('WebGLRenderingContext.DEPTH_CLEAR_VALUE')
+  @DocsEditable
   static const int DEPTH_CLEAR_VALUE = 0x0B73;
 
+  @DomName('WebGLRenderingContext.DEPTH_COMPONENT')
+  @DocsEditable
   static const int DEPTH_COMPONENT = 0x1902;
 
+  @DomName('WebGLRenderingContext.DEPTH_COMPONENT16')
+  @DocsEditable
   static const int DEPTH_COMPONENT16 = 0x81A5;
 
+  @DomName('WebGLRenderingContext.DEPTH_FUNC')
+  @DocsEditable
   static const int DEPTH_FUNC = 0x0B74;
 
+  @DomName('WebGLRenderingContext.DEPTH_RANGE')
+  @DocsEditable
   static const int DEPTH_RANGE = 0x0B70;
 
+  @DomName('WebGLRenderingContext.DEPTH_STENCIL')
+  @DocsEditable
   static const int DEPTH_STENCIL = 0x84F9;
 
+  @DomName('WebGLRenderingContext.DEPTH_STENCIL_ATTACHMENT')
+  @DocsEditable
   static const int DEPTH_STENCIL_ATTACHMENT = 0x821A;
 
+  @DomName('WebGLRenderingContext.DEPTH_TEST')
+  @DocsEditable
   static const int DEPTH_TEST = 0x0B71;
 
+  @DomName('WebGLRenderingContext.DEPTH_WRITEMASK')
+  @DocsEditable
   static const int DEPTH_WRITEMASK = 0x0B72;
 
+  @DomName('WebGLRenderingContext.DITHER')
+  @DocsEditable
   static const int DITHER = 0x0BD0;
 
+  @DomName('WebGLRenderingContext.DONT_CARE')
+  @DocsEditable
   static const int DONT_CARE = 0x1100;
 
+  @DomName('WebGLRenderingContext.DST_ALPHA')
+  @DocsEditable
   static const int DST_ALPHA = 0x0304;
 
+  @DomName('WebGLRenderingContext.DST_COLOR')
+  @DocsEditable
   static const int DST_COLOR = 0x0306;
 
+  @DomName('WebGLRenderingContext.DYNAMIC_DRAW')
+  @DocsEditable
   static const int DYNAMIC_DRAW = 0x88E8;
 
+  @DomName('WebGLRenderingContext.ELEMENT_ARRAY_BUFFER')
+  @DocsEditable
   static const int ELEMENT_ARRAY_BUFFER = 0x8893;
 
+  @DomName('WebGLRenderingContext.ELEMENT_ARRAY_BUFFER_BINDING')
+  @DocsEditable
   static const int ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
 
+  @DomName('WebGLRenderingContext.EQUAL')
+  @DocsEditable
   static const int EQUAL = 0x0202;
 
+  @DomName('WebGLRenderingContext.FASTEST')
+  @DocsEditable
   static const int FASTEST = 0x1101;
 
+  @DomName('WebGLRenderingContext.FLOAT')
+  @DocsEditable
   static const int FLOAT = 0x1406;
 
+  @DomName('WebGLRenderingContext.FLOAT_MAT2')
+  @DocsEditable
   static const int FLOAT_MAT2 = 0x8B5A;
 
+  @DomName('WebGLRenderingContext.FLOAT_MAT3')
+  @DocsEditable
   static const int FLOAT_MAT3 = 0x8B5B;
 
+  @DomName('WebGLRenderingContext.FLOAT_MAT4')
+  @DocsEditable
   static const int FLOAT_MAT4 = 0x8B5C;
 
+  @DomName('WebGLRenderingContext.FLOAT_VEC2')
+  @DocsEditable
   static const int FLOAT_VEC2 = 0x8B50;
 
+  @DomName('WebGLRenderingContext.FLOAT_VEC3')
+  @DocsEditable
   static const int FLOAT_VEC3 = 0x8B51;
 
+  @DomName('WebGLRenderingContext.FLOAT_VEC4')
+  @DocsEditable
   static const int FLOAT_VEC4 = 0x8B52;
 
+  @DomName('WebGLRenderingContext.FRAGMENT_SHADER')
+  @DocsEditable
   static const int FRAGMENT_SHADER = 0x8B30;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER')
+  @DocsEditable
   static const int FRAMEBUFFER = 0x8D40;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL')
+  @DocsEditable
   static const int FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_BINDING')
+  @DocsEditable
   static const int FRAMEBUFFER_BINDING = 0x8CA6;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_COMPLETE')
+  @DocsEditable
   static const int FRAMEBUFFER_COMPLETE = 0x8CD5;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_INCOMPLETE_ATTACHMENT')
+  @DocsEditable
   static const int FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_INCOMPLETE_DIMENSIONS')
+  @DocsEditable
   static const int FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT')
+  @DocsEditable
   static const int FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
 
+  @DomName('WebGLRenderingContext.FRAMEBUFFER_UNSUPPORTED')
+  @DocsEditable
   static const int FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
 
+  @DomName('WebGLRenderingContext.FRONT')
+  @DocsEditable
   static const int FRONT = 0x0404;
 
+  @DomName('WebGLRenderingContext.FRONT_AND_BACK')
+  @DocsEditable
   static const int FRONT_AND_BACK = 0x0408;
 
+  @DomName('WebGLRenderingContext.FRONT_FACE')
+  @DocsEditable
   static const int FRONT_FACE = 0x0B46;
 
+  @DomName('WebGLRenderingContext.FUNC_ADD')
+  @DocsEditable
   static const int FUNC_ADD = 0x8006;
 
+  @DomName('WebGLRenderingContext.FUNC_REVERSE_SUBTRACT')
+  @DocsEditable
   static const int FUNC_REVERSE_SUBTRACT = 0x800B;
 
+  @DomName('WebGLRenderingContext.FUNC_SUBTRACT')
+  @DocsEditable
   static const int FUNC_SUBTRACT = 0x800A;
 
+  @DomName('WebGLRenderingContext.GENERATE_MIPMAP_HINT')
+  @DocsEditable
   static const int GENERATE_MIPMAP_HINT = 0x8192;
 
+  @DomName('WebGLRenderingContext.GEQUAL')
+  @DocsEditable
   static const int GEQUAL = 0x0206;
 
+  @DomName('WebGLRenderingContext.GREATER')
+  @DocsEditable
   static const int GREATER = 0x0204;
 
+  @DomName('WebGLRenderingContext.GREEN_BITS')
+  @DocsEditable
   static const int GREEN_BITS = 0x0D53;
 
+  @DomName('WebGLRenderingContext.HALF_FLOAT_OES')
+  @DocsEditable
   static const int HALF_FLOAT_OES = 0x8D61;
 
+  @DomName('WebGLRenderingContext.HIGH_FLOAT')
+  @DocsEditable
   static const int HIGH_FLOAT = 0x8DF2;
 
+  @DomName('WebGLRenderingContext.HIGH_INT')
+  @DocsEditable
   static const int HIGH_INT = 0x8DF5;
 
+  @DomName('WebGLRenderingContext.INCR')
+  @DocsEditable
   static const int INCR = 0x1E02;
 
+  @DomName('WebGLRenderingContext.INCR_WRAP')
+  @DocsEditable
   static const int INCR_WRAP = 0x8507;
 
+  @DomName('WebGLRenderingContext.INT')
+  @DocsEditable
   static const int INT = 0x1404;
 
+  @DomName('WebGLRenderingContext.INT_VEC2')
+  @DocsEditable
   static const int INT_VEC2 = 0x8B53;
 
+  @DomName('WebGLRenderingContext.INT_VEC3')
+  @DocsEditable
   static const int INT_VEC3 = 0x8B54;
 
+  @DomName('WebGLRenderingContext.INT_VEC4')
+  @DocsEditable
   static const int INT_VEC4 = 0x8B55;
 
+  @DomName('WebGLRenderingContext.INVALID_ENUM')
+  @DocsEditable
   static const int INVALID_ENUM = 0x0500;
 
+  @DomName('WebGLRenderingContext.INVALID_FRAMEBUFFER_OPERATION')
+  @DocsEditable
   static const int INVALID_FRAMEBUFFER_OPERATION = 0x0506;
 
+  @DomName('WebGLRenderingContext.INVALID_OPERATION')
+  @DocsEditable
   static const int INVALID_OPERATION = 0x0502;
 
+  @DomName('WebGLRenderingContext.INVALID_VALUE')
+  @DocsEditable
   static const int INVALID_VALUE = 0x0501;
 
+  @DomName('WebGLRenderingContext.INVERT')
+  @DocsEditable
   static const int INVERT = 0x150A;
 
+  @DomName('WebGLRenderingContext.KEEP')
+  @DocsEditable
   static const int KEEP = 0x1E00;
 
+  @DomName('WebGLRenderingContext.LEQUAL')
+  @DocsEditable
   static const int LEQUAL = 0x0203;
 
+  @DomName('WebGLRenderingContext.LESS')
+  @DocsEditable
   static const int LESS = 0x0201;
 
+  @DomName('WebGLRenderingContext.LINEAR')
+  @DocsEditable
   static const int LINEAR = 0x2601;
 
+  @DomName('WebGLRenderingContext.LINEAR_MIPMAP_LINEAR')
+  @DocsEditable
   static const int LINEAR_MIPMAP_LINEAR = 0x2703;
 
+  @DomName('WebGLRenderingContext.LINEAR_MIPMAP_NEAREST')
+  @DocsEditable
   static const int LINEAR_MIPMAP_NEAREST = 0x2701;
 
+  @DomName('WebGLRenderingContext.LINES')
+  @DocsEditable
   static const int LINES = 0x0001;
 
+  @DomName('WebGLRenderingContext.LINE_LOOP')
+  @DocsEditable
   static const int LINE_LOOP = 0x0002;
 
+  @DomName('WebGLRenderingContext.LINE_STRIP')
+  @DocsEditable
   static const int LINE_STRIP = 0x0003;
 
+  @DomName('WebGLRenderingContext.LINE_WIDTH')
+  @DocsEditable
   static const int LINE_WIDTH = 0x0B21;
 
+  @DomName('WebGLRenderingContext.LINK_STATUS')
+  @DocsEditable
   static const int LINK_STATUS = 0x8B82;
 
+  @DomName('WebGLRenderingContext.LOW_FLOAT')
+  @DocsEditable
   static const int LOW_FLOAT = 0x8DF0;
 
+  @DomName('WebGLRenderingContext.LOW_INT')
+  @DocsEditable
   static const int LOW_INT = 0x8DF3;
 
+  @DomName('WebGLRenderingContext.LUMINANCE')
+  @DocsEditable
   static const int LUMINANCE = 0x1909;
 
+  @DomName('WebGLRenderingContext.LUMINANCE_ALPHA')
+  @DocsEditable
   static const int LUMINANCE_ALPHA = 0x190A;
 
+  @DomName('WebGLRenderingContext.MAX_COMBINED_TEXTURE_IMAGE_UNITS')
+  @DocsEditable
   static const int MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
 
+  @DomName('WebGLRenderingContext.MAX_CUBE_MAP_TEXTURE_SIZE')
+  @DocsEditable
   static const int MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
 
+  @DomName('WebGLRenderingContext.MAX_FRAGMENT_UNIFORM_VECTORS')
+  @DocsEditable
   static const int MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
 
+  @DomName('WebGLRenderingContext.MAX_RENDERBUFFER_SIZE')
+  @DocsEditable
   static const int MAX_RENDERBUFFER_SIZE = 0x84E8;
 
+  @DomName('WebGLRenderingContext.MAX_TEXTURE_IMAGE_UNITS')
+  @DocsEditable
   static const int MAX_TEXTURE_IMAGE_UNITS = 0x8872;
 
+  @DomName('WebGLRenderingContext.MAX_TEXTURE_SIZE')
+  @DocsEditable
   static const int MAX_TEXTURE_SIZE = 0x0D33;
 
+  @DomName('WebGLRenderingContext.MAX_VARYING_VECTORS')
+  @DocsEditable
   static const int MAX_VARYING_VECTORS = 0x8DFC;
 
+  @DomName('WebGLRenderingContext.MAX_VERTEX_ATTRIBS')
+  @DocsEditable
   static const int MAX_VERTEX_ATTRIBS = 0x8869;
 
+  @DomName('WebGLRenderingContext.MAX_VERTEX_TEXTURE_IMAGE_UNITS')
+  @DocsEditable
   static const int MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
 
+  @DomName('WebGLRenderingContext.MAX_VERTEX_UNIFORM_VECTORS')
+  @DocsEditable
   static const int MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
 
+  @DomName('WebGLRenderingContext.MAX_VIEWPORT_DIMS')
+  @DocsEditable
   static const int MAX_VIEWPORT_DIMS = 0x0D3A;
 
+  @DomName('WebGLRenderingContext.MEDIUM_FLOAT')
+  @DocsEditable
   static const int MEDIUM_FLOAT = 0x8DF1;
 
+  @DomName('WebGLRenderingContext.MEDIUM_INT')
+  @DocsEditable
   static const int MEDIUM_INT = 0x8DF4;
 
+  @DomName('WebGLRenderingContext.MIRRORED_REPEAT')
+  @DocsEditable
   static const int MIRRORED_REPEAT = 0x8370;
 
+  @DomName('WebGLRenderingContext.NEAREST')
+  @DocsEditable
   static const int NEAREST = 0x2600;
 
+  @DomName('WebGLRenderingContext.NEAREST_MIPMAP_LINEAR')
+  @DocsEditable
   static const int NEAREST_MIPMAP_LINEAR = 0x2702;
 
+  @DomName('WebGLRenderingContext.NEAREST_MIPMAP_NEAREST')
+  @DocsEditable
   static const int NEAREST_MIPMAP_NEAREST = 0x2700;
 
+  @DomName('WebGLRenderingContext.NEVER')
+  @DocsEditable
   static const int NEVER = 0x0200;
 
+  @DomName('WebGLRenderingContext.NICEST')
+  @DocsEditable
   static const int NICEST = 0x1102;
 
+  @DomName('WebGLRenderingContext.NONE')
+  @DocsEditable
   static const int NONE = 0;
 
+  @DomName('WebGLRenderingContext.NOTEQUAL')
+  @DocsEditable
   static const int NOTEQUAL = 0x0205;
 
+  @DomName('WebGLRenderingContext.NO_ERROR')
+  @DocsEditable
   static const int NO_ERROR = 0;
 
+  @DomName('WebGLRenderingContext.ONE')
+  @DocsEditable
   static const int ONE = 1;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_CONSTANT_ALPHA')
+  @DocsEditable
   static const int ONE_MINUS_CONSTANT_ALPHA = 0x8004;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_CONSTANT_COLOR')
+  @DocsEditable
   static const int ONE_MINUS_CONSTANT_COLOR = 0x8002;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_DST_ALPHA')
+  @DocsEditable
   static const int ONE_MINUS_DST_ALPHA = 0x0305;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_DST_COLOR')
+  @DocsEditable
   static const int ONE_MINUS_DST_COLOR = 0x0307;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_SRC_ALPHA')
+  @DocsEditable
   static const int ONE_MINUS_SRC_ALPHA = 0x0303;
 
+  @DomName('WebGLRenderingContext.ONE_MINUS_SRC_COLOR')
+  @DocsEditable
   static const int ONE_MINUS_SRC_COLOR = 0x0301;
 
+  @DomName('WebGLRenderingContext.OUT_OF_MEMORY')
+  @DocsEditable
   static const int OUT_OF_MEMORY = 0x0505;
 
+  @DomName('WebGLRenderingContext.PACK_ALIGNMENT')
+  @DocsEditable
   static const int PACK_ALIGNMENT = 0x0D05;
 
+  @DomName('WebGLRenderingContext.POINTS')
+  @DocsEditable
   static const int POINTS = 0x0000;
 
+  @DomName('WebGLRenderingContext.POLYGON_OFFSET_FACTOR')
+  @DocsEditable
   static const int POLYGON_OFFSET_FACTOR = 0x8038;
 
+  @DomName('WebGLRenderingContext.POLYGON_OFFSET_FILL')
+  @DocsEditable
   static const int POLYGON_OFFSET_FILL = 0x8037;
 
+  @DomName('WebGLRenderingContext.POLYGON_OFFSET_UNITS')
+  @DocsEditable
   static const int POLYGON_OFFSET_UNITS = 0x2A00;
 
+  @DomName('WebGLRenderingContext.RED_BITS')
+  @DocsEditable
   static const int RED_BITS = 0x0D52;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER')
+  @DocsEditable
   static const int RENDERBUFFER = 0x8D41;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_ALPHA_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_ALPHA_SIZE = 0x8D53;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_BINDING')
+  @DocsEditable
   static const int RENDERBUFFER_BINDING = 0x8CA7;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_BLUE_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_BLUE_SIZE = 0x8D52;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_DEPTH_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_DEPTH_SIZE = 0x8D54;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_GREEN_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_GREEN_SIZE = 0x8D51;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_HEIGHT')
+  @DocsEditable
   static const int RENDERBUFFER_HEIGHT = 0x8D43;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_INTERNAL_FORMAT')
+  @DocsEditable
   static const int RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_RED_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_RED_SIZE = 0x8D50;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_STENCIL_SIZE')
+  @DocsEditable
   static const int RENDERBUFFER_STENCIL_SIZE = 0x8D55;
 
+  @DomName('WebGLRenderingContext.RENDERBUFFER_WIDTH')
+  @DocsEditable
   static const int RENDERBUFFER_WIDTH = 0x8D42;
 
+  @DomName('WebGLRenderingContext.RENDERER')
+  @DocsEditable
   static const int RENDERER = 0x1F01;
 
+  @DomName('WebGLRenderingContext.REPEAT')
+  @DocsEditable
   static const int REPEAT = 0x2901;
 
+  @DomName('WebGLRenderingContext.REPLACE')
+  @DocsEditable
   static const int REPLACE = 0x1E01;
 
+  @DomName('WebGLRenderingContext.RGB')
+  @DocsEditable
   static const int RGB = 0x1907;
 
+  @DomName('WebGLRenderingContext.RGB565')
+  @DocsEditable
   static const int RGB565 = 0x8D62;
 
+  @DomName('WebGLRenderingContext.RGB5_A1')
+  @DocsEditable
   static const int RGB5_A1 = 0x8057;
 
+  @DomName('WebGLRenderingContext.RGBA')
+  @DocsEditable
   static const int RGBA = 0x1908;
 
+  @DomName('WebGLRenderingContext.RGBA4')
+  @DocsEditable
   static const int RGBA4 = 0x8056;
 
+  @DomName('WebGLRenderingContext.SAMPLER_2D')
+  @DocsEditable
   static const int SAMPLER_2D = 0x8B5E;
 
+  @DomName('WebGLRenderingContext.SAMPLER_CUBE')
+  @DocsEditable
   static const int SAMPLER_CUBE = 0x8B60;
 
+  @DomName('WebGLRenderingContext.SAMPLES')
+  @DocsEditable
   static const int SAMPLES = 0x80A9;
 
+  @DomName('WebGLRenderingContext.SAMPLE_ALPHA_TO_COVERAGE')
+  @DocsEditable
   static const int SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
 
+  @DomName('WebGLRenderingContext.SAMPLE_BUFFERS')
+  @DocsEditable
   static const int SAMPLE_BUFFERS = 0x80A8;
 
+  @DomName('WebGLRenderingContext.SAMPLE_COVERAGE')
+  @DocsEditable
   static const int SAMPLE_COVERAGE = 0x80A0;
 
+  @DomName('WebGLRenderingContext.SAMPLE_COVERAGE_INVERT')
+  @DocsEditable
   static const int SAMPLE_COVERAGE_INVERT = 0x80AB;
 
+  @DomName('WebGLRenderingContext.SAMPLE_COVERAGE_VALUE')
+  @DocsEditable
   static const int SAMPLE_COVERAGE_VALUE = 0x80AA;
 
+  @DomName('WebGLRenderingContext.SCISSOR_BOX')
+  @DocsEditable
   static const int SCISSOR_BOX = 0x0C10;
 
+  @DomName('WebGLRenderingContext.SCISSOR_TEST')
+  @DocsEditable
   static const int SCISSOR_TEST = 0x0C11;
 
+  @DomName('WebGLRenderingContext.SHADER_TYPE')
+  @DocsEditable
   static const int SHADER_TYPE = 0x8B4F;
 
+  @DomName('WebGLRenderingContext.SHADING_LANGUAGE_VERSION')
+  @DocsEditable
   static const int SHADING_LANGUAGE_VERSION = 0x8B8C;
 
+  @DomName('WebGLRenderingContext.SHORT')
+  @DocsEditable
   static const int SHORT = 0x1402;
 
+  @DomName('WebGLRenderingContext.SRC_ALPHA')
+  @DocsEditable
   static const int SRC_ALPHA = 0x0302;
 
+  @DomName('WebGLRenderingContext.SRC_ALPHA_SATURATE')
+  @DocsEditable
   static const int SRC_ALPHA_SATURATE = 0x0308;
 
+  @DomName('WebGLRenderingContext.SRC_COLOR')
+  @DocsEditable
   static const int SRC_COLOR = 0x0300;
 
+  @DomName('WebGLRenderingContext.STATIC_DRAW')
+  @DocsEditable
   static const int STATIC_DRAW = 0x88E4;
 
+  @DomName('WebGLRenderingContext.STENCIL_ATTACHMENT')
+  @DocsEditable
   static const int STENCIL_ATTACHMENT = 0x8D20;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_FAIL')
+  @DocsEditable
   static const int STENCIL_BACK_FAIL = 0x8801;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_FUNC')
+  @DocsEditable
   static const int STENCIL_BACK_FUNC = 0x8800;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_PASS_DEPTH_FAIL')
+  @DocsEditable
   static const int STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_PASS_DEPTH_PASS')
+  @DocsEditable
   static const int STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_REF')
+  @DocsEditable
   static const int STENCIL_BACK_REF = 0x8CA3;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_VALUE_MASK')
+  @DocsEditable
   static const int STENCIL_BACK_VALUE_MASK = 0x8CA4;
 
+  @DomName('WebGLRenderingContext.STENCIL_BACK_WRITEMASK')
+  @DocsEditable
   static const int STENCIL_BACK_WRITEMASK = 0x8CA5;
 
+  @DomName('WebGLRenderingContext.STENCIL_BITS')
+  @DocsEditable
   static const int STENCIL_BITS = 0x0D57;
 
+  @DomName('WebGLRenderingContext.STENCIL_BUFFER_BIT')
+  @DocsEditable
   static const int STENCIL_BUFFER_BIT = 0x00000400;
 
+  @DomName('WebGLRenderingContext.STENCIL_CLEAR_VALUE')
+  @DocsEditable
   static const int STENCIL_CLEAR_VALUE = 0x0B91;
 
+  @DomName('WebGLRenderingContext.STENCIL_FAIL')
+  @DocsEditable
   static const int STENCIL_FAIL = 0x0B94;
 
+  @DomName('WebGLRenderingContext.STENCIL_FUNC')
+  @DocsEditable
   static const int STENCIL_FUNC = 0x0B92;
 
+  @DomName('WebGLRenderingContext.STENCIL_INDEX')
+  @DocsEditable
   static const int STENCIL_INDEX = 0x1901;
 
+  @DomName('WebGLRenderingContext.STENCIL_INDEX8')
+  @DocsEditable
   static const int STENCIL_INDEX8 = 0x8D48;
 
+  @DomName('WebGLRenderingContext.STENCIL_PASS_DEPTH_FAIL')
+  @DocsEditable
   static const int STENCIL_PASS_DEPTH_FAIL = 0x0B95;
 
+  @DomName('WebGLRenderingContext.STENCIL_PASS_DEPTH_PASS')
+  @DocsEditable
   static const int STENCIL_PASS_DEPTH_PASS = 0x0B96;
 
+  @DomName('WebGLRenderingContext.STENCIL_REF')
+  @DocsEditable
   static const int STENCIL_REF = 0x0B97;
 
+  @DomName('WebGLRenderingContext.STENCIL_TEST')
+  @DocsEditable
   static const int STENCIL_TEST = 0x0B90;
 
+  @DomName('WebGLRenderingContext.STENCIL_VALUE_MASK')
+  @DocsEditable
   static const int STENCIL_VALUE_MASK = 0x0B93;
 
+  @DomName('WebGLRenderingContext.STENCIL_WRITEMASK')
+  @DocsEditable
   static const int STENCIL_WRITEMASK = 0x0B98;
 
+  @DomName('WebGLRenderingContext.STREAM_DRAW')
+  @DocsEditable
   static const int STREAM_DRAW = 0x88E0;
 
+  @DomName('WebGLRenderingContext.SUBPIXEL_BITS')
+  @DocsEditable
   static const int SUBPIXEL_BITS = 0x0D50;
 
+  @DomName('WebGLRenderingContext.TEXTURE')
+  @DocsEditable
   static const int TEXTURE = 0x1702;
 
+  @DomName('WebGLRenderingContext.TEXTURE0')
+  @DocsEditable
   static const int TEXTURE0 = 0x84C0;
 
+  @DomName('WebGLRenderingContext.TEXTURE1')
+  @DocsEditable
   static const int TEXTURE1 = 0x84C1;
 
+  @DomName('WebGLRenderingContext.TEXTURE10')
+  @DocsEditable
   static const int TEXTURE10 = 0x84CA;
 
+  @DomName('WebGLRenderingContext.TEXTURE11')
+  @DocsEditable
   static const int TEXTURE11 = 0x84CB;
 
+  @DomName('WebGLRenderingContext.TEXTURE12')
+  @DocsEditable
   static const int TEXTURE12 = 0x84CC;
 
+  @DomName('WebGLRenderingContext.TEXTURE13')
+  @DocsEditable
   static const int TEXTURE13 = 0x84CD;
 
+  @DomName('WebGLRenderingContext.TEXTURE14')
+  @DocsEditable
   static const int TEXTURE14 = 0x84CE;
 
+  @DomName('WebGLRenderingContext.TEXTURE15')
+  @DocsEditable
   static const int TEXTURE15 = 0x84CF;
 
+  @DomName('WebGLRenderingContext.TEXTURE16')
+  @DocsEditable
   static const int TEXTURE16 = 0x84D0;
 
+  @DomName('WebGLRenderingContext.TEXTURE17')
+  @DocsEditable
   static const int TEXTURE17 = 0x84D1;
 
+  @DomName('WebGLRenderingContext.TEXTURE18')
+  @DocsEditable
   static const int TEXTURE18 = 0x84D2;
 
+  @DomName('WebGLRenderingContext.TEXTURE19')
+  @DocsEditable
   static const int TEXTURE19 = 0x84D3;
 
+  @DomName('WebGLRenderingContext.TEXTURE2')
+  @DocsEditable
   static const int TEXTURE2 = 0x84C2;
 
+  @DomName('WebGLRenderingContext.TEXTURE20')
+  @DocsEditable
   static const int TEXTURE20 = 0x84D4;
 
+  @DomName('WebGLRenderingContext.TEXTURE21')
+  @DocsEditable
   static const int TEXTURE21 = 0x84D5;
 
+  @DomName('WebGLRenderingContext.TEXTURE22')
+  @DocsEditable
   static const int TEXTURE22 = 0x84D6;
 
+  @DomName('WebGLRenderingContext.TEXTURE23')
+  @DocsEditable
   static const int TEXTURE23 = 0x84D7;
 
+  @DomName('WebGLRenderingContext.TEXTURE24')
+  @DocsEditable
   static const int TEXTURE24 = 0x84D8;
 
+  @DomName('WebGLRenderingContext.TEXTURE25')
+  @DocsEditable
   static const int TEXTURE25 = 0x84D9;
 
+  @DomName('WebGLRenderingContext.TEXTURE26')
+  @DocsEditable
   static const int TEXTURE26 = 0x84DA;
 
+  @DomName('WebGLRenderingContext.TEXTURE27')
+  @DocsEditable
   static const int TEXTURE27 = 0x84DB;
 
+  @DomName('WebGLRenderingContext.TEXTURE28')
+  @DocsEditable
   static const int TEXTURE28 = 0x84DC;
 
+  @DomName('WebGLRenderingContext.TEXTURE29')
+  @DocsEditable
   static const int TEXTURE29 = 0x84DD;
 
+  @DomName('WebGLRenderingContext.TEXTURE3')
+  @DocsEditable
   static const int TEXTURE3 = 0x84C3;
 
+  @DomName('WebGLRenderingContext.TEXTURE30')
+  @DocsEditable
   static const int TEXTURE30 = 0x84DE;
 
+  @DomName('WebGLRenderingContext.TEXTURE31')
+  @DocsEditable
   static const int TEXTURE31 = 0x84DF;
 
+  @DomName('WebGLRenderingContext.TEXTURE4')
+  @DocsEditable
   static const int TEXTURE4 = 0x84C4;
 
+  @DomName('WebGLRenderingContext.TEXTURE5')
+  @DocsEditable
   static const int TEXTURE5 = 0x84C5;
 
+  @DomName('WebGLRenderingContext.TEXTURE6')
+  @DocsEditable
   static const int TEXTURE6 = 0x84C6;
 
+  @DomName('WebGLRenderingContext.TEXTURE7')
+  @DocsEditable
   static const int TEXTURE7 = 0x84C7;
 
+  @DomName('WebGLRenderingContext.TEXTURE8')
+  @DocsEditable
   static const int TEXTURE8 = 0x84C8;
 
+  @DomName('WebGLRenderingContext.TEXTURE9')
+  @DocsEditable
   static const int TEXTURE9 = 0x84C9;
 
+  @DomName('WebGLRenderingContext.TEXTURE_2D')
+  @DocsEditable
   static const int TEXTURE_2D = 0x0DE1;
 
+  @DomName('WebGLRenderingContext.TEXTURE_BINDING_2D')
+  @DocsEditable
   static const int TEXTURE_BINDING_2D = 0x8069;
 
+  @DomName('WebGLRenderingContext.TEXTURE_BINDING_CUBE_MAP')
+  @DocsEditable
   static const int TEXTURE_BINDING_CUBE_MAP = 0x8514;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP = 0x8513;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_X')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Y')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Z')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_X')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Y')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
 
+  @DomName('WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Z')
+  @DocsEditable
   static const int TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
 
+  @DomName('WebGLRenderingContext.TEXTURE_MAG_FILTER')
+  @DocsEditable
   static const int TEXTURE_MAG_FILTER = 0x2800;
 
+  @DomName('WebGLRenderingContext.TEXTURE_MIN_FILTER')
+  @DocsEditable
   static const int TEXTURE_MIN_FILTER = 0x2801;
 
+  @DomName('WebGLRenderingContext.TEXTURE_WRAP_S')
+  @DocsEditable
   static const int TEXTURE_WRAP_S = 0x2802;
 
+  @DomName('WebGLRenderingContext.TEXTURE_WRAP_T')
+  @DocsEditable
   static const int TEXTURE_WRAP_T = 0x2803;
 
+  @DomName('WebGLRenderingContext.TRIANGLES')
+  @DocsEditable
   static const int TRIANGLES = 0x0004;
 
+  @DomName('WebGLRenderingContext.TRIANGLE_FAN')
+  @DocsEditable
   static const int TRIANGLE_FAN = 0x0006;
 
+  @DomName('WebGLRenderingContext.TRIANGLE_STRIP')
+  @DocsEditable
   static const int TRIANGLE_STRIP = 0x0005;
 
+  @DomName('WebGLRenderingContext.UNPACK_ALIGNMENT')
+  @DocsEditable
   static const int UNPACK_ALIGNMENT = 0x0CF5;
 
+  @DomName('WebGLRenderingContext.UNPACK_COLORSPACE_CONVERSION_WEBGL')
+  @DocsEditable
   static const int UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
 
+  @DomName('WebGLRenderingContext.UNPACK_FLIP_Y_WEBGL')
+  @DocsEditable
   static const int UNPACK_FLIP_Y_WEBGL = 0x9240;
 
+  @DomName('WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL')
+  @DocsEditable
   static const int UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_BYTE')
+  @DocsEditable
   static const int UNSIGNED_BYTE = 0x1401;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_INT')
+  @DocsEditable
   static const int UNSIGNED_INT = 0x1405;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT')
+  @DocsEditable
   static const int UNSIGNED_SHORT = 0x1403;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT_4_4_4_4')
+  @DocsEditable
   static const int UNSIGNED_SHORT_4_4_4_4 = 0x8033;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT_5_5_5_1')
+  @DocsEditable
   static const int UNSIGNED_SHORT_5_5_5_1 = 0x8034;
 
+  @DomName('WebGLRenderingContext.UNSIGNED_SHORT_5_6_5')
+  @DocsEditable
   static const int UNSIGNED_SHORT_5_6_5 = 0x8363;
 
+  @DomName('WebGLRenderingContext.VALIDATE_STATUS')
+  @DocsEditable
   static const int VALIDATE_STATUS = 0x8B83;
 
+  @DomName('WebGLRenderingContext.VENDOR')
+  @DocsEditable
   static const int VENDOR = 0x1F00;
 
+  @DomName('WebGLRenderingContext.VERSION')
+  @DocsEditable
   static const int VERSION = 0x1F02;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_ENABLED')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_NORMALIZED')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_POINTER')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_SIZE')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_STRIDE')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
 
+  @DomName('WebGLRenderingContext.VERTEX_ATTRIB_ARRAY_TYPE')
+  @DocsEditable
   static const int VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
 
+  @DomName('WebGLRenderingContext.VERTEX_SHADER')
+  @DocsEditable
   static const int VERTEX_SHADER = 0x8B31;
 
+  @DomName('WebGLRenderingContext.VIEWPORT')
+  @DocsEditable
   static const int VIEWPORT = 0x0BA2;
 
+  @DomName('WebGLRenderingContext.ZERO')
+  @DocsEditable
   static const int ZERO = 0;
 
   @DomName('WebGLRenderingContext.drawingBufferHeight')
diff --git a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
index 851be05..b4990c4 100644
--- a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -17,6 +17,7 @@
 import 'dart:html_common';
 import 'dart:_js_helper' show convertDartClosureToJS, Creates, JavaScriptIndexingBehavior, JSName;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show Interceptor;
 // DO NOT EDIT - unless you are editing documentation as per:
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:audio library.
@@ -108,20 +109,36 @@
 @DomName('SQLError')
 class SqlError native "SQLError" {
 
+  @DomName('SQLError.CONSTRAINT_ERR')
+  @DocsEditable
   static const int CONSTRAINT_ERR = 6;
 
+  @DomName('SQLError.DATABASE_ERR')
+  @DocsEditable
   static const int DATABASE_ERR = 1;
 
+  @DomName('SQLError.QUOTA_ERR')
+  @DocsEditable
   static const int QUOTA_ERR = 4;
 
+  @DomName('SQLError.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 5;
 
+  @DomName('SQLError.TIMEOUT_ERR')
+  @DocsEditable
   static const int TIMEOUT_ERR = 7;
 
+  @DomName('SQLError.TOO_LARGE_ERR')
+  @DocsEditable
   static const int TOO_LARGE_ERR = 3;
 
+  @DomName('SQLError.UNKNOWN_ERR')
+  @DocsEditable
   static const int UNKNOWN_ERR = 0;
 
+  @DomName('SQLError.VERSION_ERR')
+  @DocsEditable
   static const int VERSION_ERR = 2;
 
   @DomName('SQLError.code')
@@ -141,20 +158,36 @@
 @DomName('SQLException')
 class SqlException native "SQLException" {
 
+  @DomName('SQLException.CONSTRAINT_ERR')
+  @DocsEditable
   static const int CONSTRAINT_ERR = 6;
 
+  @DomName('SQLException.DATABASE_ERR')
+  @DocsEditable
   static const int DATABASE_ERR = 1;
 
+  @DomName('SQLException.QUOTA_ERR')
+  @DocsEditable
   static const int QUOTA_ERR = 4;
 
+  @DomName('SQLException.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 5;
 
+  @DomName('SQLException.TIMEOUT_ERR')
+  @DocsEditable
   static const int TIMEOUT_ERR = 7;
 
+  @DomName('SQLException.TOO_LARGE_ERR')
+  @DocsEditable
   static const int TOO_LARGE_ERR = 3;
 
+  @DomName('SQLException.UNKNOWN_ERR')
+  @DocsEditable
   static const int UNKNOWN_ERR = 0;
 
+  @DomName('SQLException.VERSION_ERR')
+  @DocsEditable
   static const int VERSION_ERR = 2;
 
   @DomName('SQLException.code')
@@ -193,14 +226,18 @@
 
 @DocsEditable
 @DomName('SQLResultSetRowList')
-class SqlResultSetRowList extends Object with ListMixin<Map>, ImmutableListMixin<Map> implements JavaScriptIndexingBehavior, List<Map> native "SQLResultSetRowList" {
+class SqlResultSetRowList extends Interceptor with ListMixin<Map>, ImmutableListMixin<Map> implements JavaScriptIndexingBehavior, List<Map> native "SQLResultSetRowList" {
 
   @DomName('SQLResultSetRowList.length')
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Map operator[](int index) => this.item(index);
-
+  Map operator[](int index) {
+    if (JS("bool", "# >>> 0 !== # || # >= #", index,
+        index, index, length))
+      throw new RangeError.range(index, 0, length);
+    return this.item(index);
+  }
   void operator[]=(int index, Map value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
@@ -212,6 +249,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Map get first {
+    if (this.length > 0) {
+      return JS('Map', '#[0]', this);
+    }
+    throw new StateError("No elements");
+  }
+
+  Map get last {
+    int len = this.length;
+    if (len > 0) {
+      return JS('Map', '#[#]', this, len - 1);
+    }
+    throw new StateError("No elements");
+  }
+
+  Map get single {
+    int len = this.length;
+    if (len == 1) {
+      return JS('Map', '#[0]', this);
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Map elementAt(int index) => this[index];
   // -- end List<Map> mixins.
 
   @DomName('SQLResultSetRowList.item')
diff --git a/sdk/lib/web_sql/dartium/web_sql_dartium.dart b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
index c7c3bc0..f33d285 100644
--- a/sdk/lib/web_sql/dartium/web_sql_dartium.dart
+++ b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
@@ -114,20 +114,36 @@
 class SqlError extends NativeFieldWrapperClass1 {
   SqlError.internal();
 
+  @DomName('SQLError.CONSTRAINT_ERR')
+  @DocsEditable
   static const int CONSTRAINT_ERR = 6;
 
+  @DomName('SQLError.DATABASE_ERR')
+  @DocsEditable
   static const int DATABASE_ERR = 1;
 
+  @DomName('SQLError.QUOTA_ERR')
+  @DocsEditable
   static const int QUOTA_ERR = 4;
 
+  @DomName('SQLError.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 5;
 
+  @DomName('SQLError.TIMEOUT_ERR')
+  @DocsEditable
   static const int TIMEOUT_ERR = 7;
 
+  @DomName('SQLError.TOO_LARGE_ERR')
+  @DocsEditable
   static const int TOO_LARGE_ERR = 3;
 
+  @DomName('SQLError.UNKNOWN_ERR')
+  @DocsEditable
   static const int UNKNOWN_ERR = 0;
 
+  @DomName('SQLError.VERSION_ERR')
+  @DocsEditable
   static const int VERSION_ERR = 2;
 
   @DomName('SQLError.code')
@@ -151,20 +167,36 @@
 class SqlException extends NativeFieldWrapperClass1 {
   SqlException.internal();
 
+  @DomName('SQLException.CONSTRAINT_ERR')
+  @DocsEditable
   static const int CONSTRAINT_ERR = 6;
 
+  @DomName('SQLException.DATABASE_ERR')
+  @DocsEditable
   static const int DATABASE_ERR = 1;
 
+  @DomName('SQLException.QUOTA_ERR')
+  @DocsEditable
   static const int QUOTA_ERR = 4;
 
+  @DomName('SQLException.SYNTAX_ERR')
+  @DocsEditable
   static const int SYNTAX_ERR = 5;
 
+  @DomName('SQLException.TIMEOUT_ERR')
+  @DocsEditable
   static const int TIMEOUT_ERR = 7;
 
+  @DomName('SQLException.TOO_LARGE_ERR')
+  @DocsEditable
   static const int TOO_LARGE_ERR = 3;
 
+  @DomName('SQLException.UNKNOWN_ERR')
+  @DocsEditable
   static const int UNKNOWN_ERR = 0;
 
+  @DomName('SQLException.VERSION_ERR')
+  @DocsEditable
   static const int VERSION_ERR = 2;
 
   @DomName('SQLException.code')
@@ -217,7 +249,12 @@
   @DocsEditable
   int get length native "SQLResultSetRowList_length_Getter";
 
-  Map operator[](int index) native "SQLResultSetRowList_item_Callback";
+  Map operator[](int index) {
+    if (index < 0 || index >= length)
+      throw new RangeError.range(index, 0, length);
+    return _nativeIndexedGetter(index);
+  }
+  Map _nativeIndexedGetter(int index) native "SQLResultSetRowList_item_Callback";
 
   void operator[]=(int index, Map value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -230,6 +267,31 @@
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
+  Map get first {
+    if (this.length > 0) {
+      return this[0];
+    }
+    throw new StateError("No elements");
+  }
+
+  Map get last {
+    int len = this.length;
+    if (len > 0) {
+      return this[len - 1];
+    }
+    throw new StateError("No elements");
+  }
+
+  Map get single {
+    int len = this.length;
+    if (len == 1) {
+      return this[0];
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  Map elementAt(int index) => this[index];
   // -- end List<Map> mixins.
 
   @DomName('SQLResultSetRowList.item')
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index d0e06b3..2dd3d58 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -29,28 +29,6 @@
 Language/07_Classes/07_Classes_A09_t02: fail
 Language/07_Classes/07_Classes_A09_t03: fail
 Language/07_Classes/07_Classes_A09_t04: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A03_t01: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A03_t02: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t02: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t03: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t04: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t05: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t06: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t07: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t08: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t09: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t10: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t11: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t12: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t13: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t14: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t15: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t16: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t17: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A04_t18: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A05_t02: fail
-Language/07_Classes/1_Instance_Methods/2_Operators_A06_t02: fail
-Language/07_Classes/1_Instance_Methods_A02_t05: fail
 Language/07_Classes/2_Getters_A04_t03: fail
 Language/07_Classes/2_Getters_A04_t04: fail
 Language/07_Classes/2_Getters_A04_t05: fail
@@ -59,7 +37,6 @@
 Language/07_Classes/3_Setters_A03_t04: fail
 Language/07_Classes/3_Setters_A03_t06: fail
 Language/07_Classes/3_Setters_A03_t08: fail
-Language/07_Classes/4_Abstract_Instance_Members_A04_t06: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A01_t04: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t03: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t04: fail
@@ -85,9 +62,6 @@
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A16_t02: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A16_t07: fail
 Language/07_Classes/6_Constructors/2_Factories_A01_t05: fail
-Language/07_Classes/6_Constructors/2_Factories_A02_t03: fail
-Language/07_Classes/6_Constructors/2_Factories_A02_t04: fail
-Language/07_Classes/6_Constructors/2_Factories_A02_t05: fail
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t02: fail
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: fail
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: fail
@@ -143,19 +117,6 @@
 Language/11_Expressions/08_Throw_A06_t05: fail
 Language/11_Expressions/08_Throw_A06_t06: fail
 Language/11_Expressions/11_Instance_Creation/1_New_A01_t04: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A02_t01: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A02_t02: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A02_t03: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A02_t04: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A02_t05: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A02_t06: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A02_t07: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A03_t01: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A03_t02: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A04_t01: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A04_t03: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A04_t04: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A05_t01: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A06_t01: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A06_t02: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: fail
@@ -166,12 +127,6 @@
 Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A01_t05: fail
 Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A01_t05: fail
 Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A01_t05: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A05_t01: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A05_t02: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A05_t04: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A05_t05: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A05_t06: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A05_t07: fail
 Language/11_Expressions/19_Conditional_A01_t05: fail
 Language/11_Expressions/19_Conditional_A01_t06: fail
 Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t04: fail
@@ -212,7 +167,6 @@
 Language/11_Expressions/24_Shift_A01_t07: fail
 Language/11_Expressions/25_Additive_Expressions_A01_t02: fail
 Language/11_Expressions/25_Additive_Expressions_A01_t03: fail
-Language/11_Expressions/25_Additive_Expressions_A01_t05: fail
 Language/11_Expressions/25_Additive_Expressions_A01_t06: fail
 Language/11_Expressions/26_Multiplicative_Expressions_A01_t02: fail
 Language/11_Expressions/26_Multiplicative_Expressions_A01_t03: fail
@@ -250,7 +204,6 @@
 Language/11_Expressions/33_Argument_Definition_Test_A01_t14: fail
 Language/11_Expressions/33_Argument_Definition_Test_A01_t18: fail
 Language/12_Statements/02_Expression_Statements_A01_t06: fail
-Language/12_Statements/02_Expression_Statements_A01_t07: fail
 Language/12_Statements/02_Expression_Statements_A01_t12: fail
 Language/12_Statements/03_Variable_Declaration_A04_t01: fail
 Language/12_Statements/03_Variable_Declaration_A04_t02: fail
@@ -272,9 +225,7 @@
 Language/13_Libraries_and_Scripts/1_Imports_A02_t12: fail
 Language/13_Libraries_and_Scripts/1_Imports_A02_t15: fail
 Language/13_Libraries_and_Scripts/1_Imports_A04_t03: fail
-Language/13_Libraries_and_Scripts/1_Imports_A05_t01: fail
-Language/13_Libraries_and_Scripts/2_Exports_A04_t02: fail
-Language/13_Libraries_and_Scripts/2_Exports_A04_t03: fail
+Language/13_Libraries_and_Scripts/1_Imports_A05_t01: fail # co19 issue 411
 Language/13_Libraries_and_Scripts/2_Exports_A05_t01: fail
 Language/13_Libraries_and_Scripts/5_URIs_A01_t24: fail
 Language/13_Libraries_and_Scripts/5_URIs_A01_t25: fail
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index 582f8aa..93ae53c 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -27,7 +27,8 @@
 // TODO(johnniwinther): Support canonical URIs as keys and message kinds as
 // values.
 const Map<String,List<String>> WHITE_LIST = const {
-  'html_dart2js.dart': const ['Warning: Using "new Symbol"'], // Issue 10565.
+  'html_dart2js.dart': const ['Warning: Using "new Symbol"', // Issue 10565.
+                              'Warning: unreachable code'], // Issue 10617.
 };
 
 class CollectingDiagnosticHandler extends FormattingDiagnosticHandler {
diff --git a/tests/compiler/dart2js/inverse_operator_test.dart b/tests/compiler/dart2js/inverse_operator_test.dart
index 6bf6ca6..e6c7cd5 100644
--- a/tests/compiler/dart2js/inverse_operator_test.dart
+++ b/tests/compiler/dart2js/inverse_operator_test.dart
@@ -9,6 +9,7 @@
 main() {
   var x = 1;
   if (inscrutable(x) == 0) {
+    main();
     x = 2;
   }
   print(!(1 < x));
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 877c3d1..07350f9 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -49,6 +49,8 @@
   setRuntimeTypeInfo(a, b) {}
   getRuntimeTypeInfo(a) {}
   stringTypeCheck(x) {}
+  stringTypeCast(x) {}
+  propertyTypeCast(x) {}
   boolConversionCheck(x) {}
   abstract class JavaScriptIndexingBehavior {}
   class JSInvocationMirror {}
diff --git a/tests/compiler/dart2js/pretty_parameter_test.dart b/tests/compiler/dart2js/pretty_parameter_test.dart
index ffd8cd4..91f00fd 100644
--- a/tests/compiler/dart2js/pretty_parameter_test.dart
+++ b/tests/compiler/dart2js/pretty_parameter_test.dart
@@ -21,6 +21,7 @@
   {
     var t0 = 2;
     if (b) {
+      bar(1, 2);
       t0 = 4;
     } else {
       t0 = 3;
@@ -62,6 +63,7 @@
 int foo(var start, bool test) {
   var result = start;
   if (test) {
+    foo(1, 2);
     result = 42;
   }
   print(result);
@@ -89,7 +91,6 @@
   Expect.isFalse(generated.contains('var'));
 
   generated = compile(PARAMETER_INIT, entry: 'foo');
-  Expect.isTrue(generated.contains('var result = test === true ? 42 : start'));
   // Check that there is only one var declaration.
   checkNumberOfMatches(new RegExp("var").allMatches(generated).iterator, 1);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index db2572a..b9f6723 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -83,6 +83,16 @@
   return 42.abs(42);
 }
 
+returnAsString() {
+  return topLevelGetter() as String;
+}
+
+typedef int Foo();
+
+returnAsTypedef() {
+  return topLevelGetter() as Foo;
+}
+
 get topLevelGetter => 42;
 returnDynamic() => topLevelGetter(42);
 
@@ -132,6 +142,8 @@
   returnDynamic();
   returnDynamic1();
   returnDynamic2();
+  returnAsString();
+  returnAsTypedef();
   new A() == null;
   new A()..returnInt1()
          ..returnInt2()
@@ -180,6 +192,9 @@
   checkReturn('returnInt8', typesInferrer.intType);
   checkReturn('returnDynamic1', typesInferrer.dynamicType);
   checkReturn('returnDynamic2', typesInferrer.dynamicType);
+  checkReturn('returnAsString',
+      new TypeMask.subtype(compiler.stringClass.computeType(compiler)));
+  checkReturn('returnAsTypedef', typesInferrer.functionType.nullable());
 
   checkReturnInClass(String className, String methodName, type) {
     var cls = findElement(compiler, className);
diff --git a/tests/compiler/dart2js/ssa_phi_codegen_test.dart b/tests/compiler/dart2js/ssa_phi_codegen_test.dart
index 96c9372..9a1a0ed 100644
--- a/tests/compiler/dart2js/ssa_phi_codegen_test.dart
+++ b/tests/compiler/dart2js/ssa_phi_codegen_test.dart
@@ -14,6 +14,7 @@
     a = 3;
   }
   print(a);
+  print(a);
 }
 """;
 
diff --git a/tests/compiler/dart2js/static_closure_test.dart b/tests/compiler/dart2js/static_closure_test.dart
index cbb53e1..e6aff7a 100644
--- a/tests/compiler/dart2js/static_closure_test.dart
+++ b/tests/compiler/dart2js/static_closure_test.dart
@@ -17,5 +17,5 @@
 
   // If this test fail, please take a look at the use of
   // toStringWrapper in captureStackTrace in js_helper.dart.
-  Expect.isTrue(code.contains(r'print($.main);'));
+  Expect.isTrue(code.contains(r'print($.main$closure);'));
 }
diff --git a/tests/html/binding_syntax_test.dart b/tests/html/binding_syntax_test.dart
index 0aa7732..4e89a0a 100644
--- a/tests/html/binding_syntax_test.dart
+++ b/tests/html/binding_syntax_test.dart
@@ -24,7 +24,7 @@
   var testDiv;
 
   setUp(() {
-    document.body.nodes.add(testDiv = new DivElement());
+    document.body.append(testDiv = new DivElement());
   });
 
   tearDown(() {
@@ -35,7 +35,7 @@
   createTestHtml(s) {
     var div = new DivElement();
     div.innerHtml = s;
-    testDiv.nodes.add(div);
+    testDiv.append(div);
 
     for (var node in div.queryAll('*')) {
       if (node.isTemplate) TemplateElement.decorate(node);
diff --git a/tests/html/canvas_pixel_array_type_alias_test.dart b/tests/html/canvas_pixel_array_type_alias_test.dart
index bcde1f4..250824d 100644
--- a/tests/html/canvas_pixel_array_type_alias_test.dart
+++ b/tests/html/canvas_pixel_array_type_alias_test.dart
@@ -19,7 +19,7 @@
   canvas = new Element.tag('canvas');
   canvas.width = width;
   canvas.height = height;
-  document.body.nodes.add(canvas);
+  document.body.append(canvas);
 
   context = canvas.getContext('2d');
 
diff --git a/tests/html/canvas_test.dart b/tests/html/canvas_test.dart
index f343b32..97f6119 100644
--- a/tests/html/canvas_test.dart
+++ b/tests/html/canvas_test.dart
@@ -10,7 +10,7 @@
   int height = 100;
 
   canvas = new CanvasElement(width:width, height:height);
-  document.body.nodes.add(canvas);
+  document.body.append(canvas);
 
   context = canvas.context2D;
 
diff --git a/tests/html/client_rect_test.dart b/tests/html/client_rect_test.dart
index 658449a..76751da 100644
--- a/tests/html/client_rect_test.dart
+++ b/tests/html/client_rect_test.dart
@@ -15,7 +15,7 @@
     block of text multiple times to see each line
     highlight with every click of the mouse button.
     ''';
-    document.body.nodes.add(element);
+    document.body.append(element);
     return element;
   }
 
diff --git a/tests/html/cross_frame_test.dart b/tests/html/cross_frame_test.dart
index dd5b4be..cc852f8 100644
--- a/tests/html/cross_frame_test.dart
+++ b/tests/html/cross_frame_test.dart
@@ -15,7 +15,7 @@
   var isHistory = predicate((x) => x is History, 'is a History');
 
   final iframe = new Element.tag('iframe');
-  document.body.nodes.add(iframe);
+  document.body.append(iframe);
 
   test('window', () {
       expect(window, isWindow);
diff --git a/tests/html/css_test.dart b/tests/html/css_test.dart
index b335d65..01a05d0 100644
--- a/tests/html/css_test.dart
+++ b/tests/html/css_test.dart
@@ -28,7 +28,7 @@
           background-color: red;
           -webkit-transform: translate3d(250px, 100px, 0px);
           ''';
-        document.body.nodes.add(element);
+        document.body.append(element);
 
         Point point = new Point(5, 2);
         checkPoint(5, 2, point);
diff --git a/tests/html/custom_element_bindings_test.dart b/tests/html/custom_element_bindings_test.dart
new file mode 100644
index 0000000..c80c5fb
--- /dev/null
+++ b/tests/html/custom_element_bindings_test.dart
@@ -0,0 +1,286 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library custom_element_bindings_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:mdv_observe/mdv_observe.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/unittest.dart';
+import 'mdv_observe_utils.dart';
+
+main() {
+  useHtmlConfiguration();
+  group('Custom Element Bindings', customElementBindingsTest);
+}
+
+sym(x) => new Symbol(x);
+
+customElementBindingsTest() {
+  var testDiv;
+
+  setUp(() {
+    document.body.append(testDiv = new DivElement());
+  });
+
+  tearDown(() {
+    testDiv.remove();
+    testDiv = null;
+  });
+
+  createTestHtml(s) {
+    var div = new DivElement();
+    div.innerHtml = s;
+    testDiv.append(div);
+
+    for (var node in div.queryAll('*')) {
+      if (node.isTemplate) TemplateElement.decorate(node);
+    }
+
+    return div;
+  }
+
+
+  test('override bind/unbind/unbindAll', () {
+    var element = new MyCustomElement();
+    var model = toSymbolMap({'a': new Point(123, 444), 'b': new Monster(100)});
+
+    element.bind('my-point', model, 'a');
+    element.bind('scary-monster', model, 'b');
+
+    expect(element.attributes, isNot(contains('my-point')));
+    expect(element.attributes, isNot(contains('scary-monster')));
+
+    expect(element.myPoint, model[sym('a')]);
+    expect(element.scaryMonster, model[sym('b')]);
+
+    model[sym('a')] = null;
+    deliverChangeRecords();
+    expect(element.myPoint, null);
+    element.unbind('my-point');
+
+    model[sym('a')] = new Point(1, 2);
+    model[sym('b')] = new Monster(200);
+    deliverChangeRecords();
+    expect(element.scaryMonster, model[sym('b')]);
+    expect(element.myPoint, null, reason: 'a was unbound');
+
+    element.unbindAll();
+    model[sym('b')] = null;
+    deliverChangeRecords();
+    expect(element.scaryMonster.health, 200);
+  });
+
+  test('override attribute setter', () {
+    var element = new WithAttrsCustomElement().real;
+    var model = toSymbolMap({'a': 1, 'b': 2});
+    element.bind('hidden?', model, 'a');
+    element.bind('id', model, 'b');
+
+    expect(element.attributes, contains('hidden'));
+    expect(element.attributes['hidden'], '');
+    expect(element.id, '2');
+
+    model[sym('a')] = null;
+    deliverChangeRecords();
+    expect(element.attributes, isNot(contains('hidden')),
+        reason: 'null is false-y');
+
+    model[sym('a')] = false;
+    deliverChangeRecords();
+    expect(element.attributes, isNot(contains('hidden')));
+
+    model[sym('a')] = 'foo';
+    model[sym('b')] = 'x';
+    deliverChangeRecords();
+    expect(element.attributes, contains('hidden'));
+    expect(element.attributes['hidden'], '');
+    expect(element.id, 'x');
+
+    expect(element.xtag.attributes.log, [
+      ['remove', 'hidden?'],
+      ['[]=', 'hidden', ''],
+      ['remove', 'id'],
+      ['[]=', 'id', '2'],
+      ['remove', 'hidden'],
+      ['remove', 'hidden'],
+      ['[]=', 'hidden', ''],
+      ['[]=', 'id', 'x'],
+    ]);
+  });
+
+  test('template bind uses overridden custom element bind', () {
+
+    var model = toSymbolMap({'a': new Point(123, 444), 'b': new Monster(100)});
+
+    var div = createTestHtml('<template bind>'
+          '<my-custom-element my-point="{{a}}" scary-monster="{{b}}">'
+          '</my-custom-element>'
+        '</template>');
+
+    TemplateElement.instanceCreated.listen((fragment) {
+      for (var e in fragment.queryAll('my-custom-element')) {
+        new MyCustomElement.attach(e);
+      }
+    });
+
+    div.query('template').model = model;
+    deliverChangeRecords();
+
+    var element = div.nodes[1];
+
+    expect(element.xtag is MyCustomElement, true,
+        reason: '${element.xtag} should be a MyCustomElement');
+
+    expect(element.xtag.myPoint, model[sym('a')]);
+    expect(element.xtag.scaryMonster, model[sym('b')]);
+
+    expect(element.attributes, isNot(contains('my-point')));
+    expect(element.attributes, isNot(contains('scary-monster')));
+
+    model[sym('a')] = null;
+    deliverChangeRecords();
+    expect(element.xtag.myPoint, null);
+
+    div.query('template').model = null;
+    deliverChangeRecords();
+
+    expect(element.parentNode, null, reason: 'element was detached');
+
+    model[sym('a')] = new Point(1, 2);
+    model[sym('b')] = new Monster(200);
+    deliverChangeRecords();
+
+    expect(element.xtag.myPoint, null, reason: 'model was unbound');
+    expect(element.xtag.scaryMonster.health, 100, reason: 'model was unbound');
+  });
+
+}
+
+class Monster {
+  int health;
+  Monster(this.health);
+}
+
+/** Demonstrates a custom element overriding bind/unbind/unbindAll. */
+class MyCustomElement implements Element {
+  final Element real;
+
+  Point myPoint;
+  Monster scaryMonster;
+
+  StreamSubscription _sub1, _sub2;
+
+  MyCustomElement() : this.attach(new Element.tag('my-custom-element'));
+
+  MyCustomElement.attach(this.real) {
+    real.xtag = this;
+  }
+
+
+  get attributes => real.attributes;
+
+  void bind(String name, model, String path) {
+    switch (name) {
+      case 'my-point':
+        unbind('my-point');
+        attributes.remove('my-point');
+
+        _sub1 = new PathObserver(model, path).bindSync((v) {
+          myPoint = v;
+        });
+        return;
+      case 'scary-monster':
+        unbind('scary-monster');
+        attributes.remove('scary-monster');
+
+        _sub2 = new PathObserver(model, path).bindSync((v) {
+          scaryMonster = v;
+        });
+        return;
+    }
+    real.bind(name, model, path);
+  }
+
+  void unbind(String name) {
+    switch (name) {
+      case 'my-point':
+        if (_sub1 != null) {
+          print('!!! unbind $name');
+          _sub1.cancel();
+          _sub1 = null;
+        }
+        return;
+      case 'scary-monster':
+        if (_sub2 != null) {
+          print('!!! unbind $name');
+          _sub2.cancel();
+          _sub2 = null;
+        }
+        return;
+    }
+    real.unbind(name);
+  }
+
+  void unbindAll() {
+    unbind('my-point');
+    unbind('scary-monster');
+    real.unbindAll();
+  }
+}
+
+/**
+ * Demonstrates a custom element can override attributes []= and remove.
+ * and see changes that the data binding system is making to the attributes.
+ */
+class WithAttrsCustomElement implements Element {
+  final Element real;
+  final AttributeMapWrapper<String, String> attributes;
+
+  factory WithAttrsCustomElement() {
+    var real = new Element.tag('with-attrs-custom-element');
+    var attributes = new AttributeMapWrapper(real.attributes);
+    return new WithAttrsCustomElement._(real, attributes);
+  }
+
+  WithAttrsCustomElement._(this.real, this.attributes) {
+    real.xtag = this;
+  }
+
+  void bind(String name, model, String path) => real.bind(name, model, path);
+  void unbind(String name) => real.unbind(name);
+  void unbindAll() => real.unbindAll();
+}
+
+// TODO(jmesserly): would be nice to use mocks when mirrors work on dart2js.
+class AttributeMapWrapper<K, V> implements Map<K, V> {
+  final List log = [];
+  Map<K, V> _map;
+
+  AttributeMapWrapper(this._map);
+
+  bool containsValue(V value) => _map.containsValue(value);
+  bool containsKey(K key) => _map.containsKey(key);
+  V operator [](K key) => _map[key];
+
+  void operator []=(K key, V value) {
+    log.add(['[]=', key, value]);
+    _map[key] = value;
+  }
+
+  V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent);
+
+  V remove(K key) {
+    log.add(['remove', key]);
+    _map.remove(key);
+  }
+
+  void clear() => _map.clear();
+  void forEach(void f(K key, V value)) => _map.forEach(f);
+  Iterable<K> get keys => _map.keys;
+  Iterable<V> get values => _map.values;
+  int get length => _map.length;
+  bool get isEmpty => _map.isEmpty;
+}
diff --git a/tests/html/dart_object_local_storage_test.dart b/tests/html/dart_object_local_storage_test.dart
index 14fde11..32050d3 100644
--- a/tests/html/dart_object_local_storage_test.dart
+++ b/tests/html/dart_object_local_storage_test.dart
@@ -16,7 +16,7 @@
   Storage sessionStorage = window.sessionStorage;
   var element = new Element.tag('canvas');
   element.id = 'test';
-  body.nodes.add(element);
+  body.append(element);
 
   test('body', () {
       expect(body, equals(document.body));
diff --git a/tests/html/datalistelement_test.dart b/tests/html/datalistelement_test.dart
index b7fe779..b69bbdb 100644
--- a/tests/html/datalistelement_test.dart
+++ b/tests/html/datalistelement_test.dart
@@ -17,7 +17,7 @@
 
   setUp(() {
       div = new DivElement();
-      document.body.nodes.add(div);
+      document.body.append(div);
       div.innerHtml = """
 <input id="input" list="browsers" />
 <datalist id="browsers">
diff --git a/tests/html/documentfragment_test.dart b/tests/html/documentfragment_test.dart
index 8146e1f..d384c98 100644
--- a/tests/html/documentfragment_test.dart
+++ b/tests/html/documentfragment_test.dart
@@ -161,7 +161,7 @@
 
   test('setting innerHtml works', () {
     var fragment = new DocumentFragment();
-    fragment.nodes.add(new Text("foo"));
+    fragment.append(new Text("foo"));
     fragment.innerHtml = "<a>bar</a>baz";
     expect(_nodeStrings(fragment.nodes), equals(["A", "baz"]));
   });
diff --git a/tests/html/element_bindings_test.dart b/tests/html/element_bindings_test.dart
index e452e0b..b960c99 100644
--- a/tests/html/element_bindings_test.dart
+++ b/tests/html/element_bindings_test.dart
@@ -27,7 +27,7 @@
   var testDiv;
 
   setUp(() {
-    document.body.nodes.add(testDiv = new DivElement());
+    document.body.append(testDiv = new DivElement());
   });
 
   tearDown(() {
@@ -41,7 +41,7 @@
 
   test('Text', () {
     var template = new Element.html('<template bind>{{a}} and {{b}}');
-    testDiv.nodes.add(template);
+    testDiv.append(template);
     var model = toSymbolMap({'a': 1, 'b': 2});
     template.model = model;
     deliverChangeRecords();
@@ -112,8 +112,8 @@
     el.text = 'dummy';
     el.nodes.first.text = 'Hello {{ adj }} {{noun}}!';
     var template = new Element.html('<template bind>');
-    template.content.nodes.add(el);
-    testDiv.nodes.add(template);
+    template.content.append(el);
+    testDiv.append(template);
     template.model = model;
 
     deliverChangeRecords();
@@ -172,7 +172,7 @@
     var model = toSymbolMap({'val': true});
 
     var el = new InputElement();
-    testDiv.nodes.add(el);
+    testDiv.append(el);
     el.type = 'checkbox';
     el.bind('checked', model, 'val');
     deliverChangeRecords();
@@ -197,25 +197,25 @@
     var container = testDiv;
 
     var el1 = new InputElement();
-    testDiv.nodes.add(el1);
+    testDiv.append(el1);
     el1.type = 'radio';
     el1.name = RADIO_GROUP_NAME;
     el1.bind('checked', model, 'val1');
 
     var el2 = new InputElement();
-    testDiv.nodes.add(el2);
+    testDiv.append(el2);
     el2.type = 'radio';
     el2.name = RADIO_GROUP_NAME;
     el2.bind('checked', model, 'val2');
 
     var el3 = new InputElement();
-    testDiv.nodes.add(el3);
+    testDiv.append(el3);
     el3.type = 'radio';
     el3.name = RADIO_GROUP_NAME;
     el3.bind('checked', model, 'val3');
 
     var el4 = new InputElement();
-    testDiv.nodes.add(el4);
+    testDiv.append(el4);
     el4.type = 'radio';
     el4.name = 'othergroup';
     el4.bind('checked', model, 'val4');
@@ -255,30 +255,30 @@
     var RADIO_GROUP_NAME = 'test';
 
     var form1 = new FormElement();
-    testDiv.nodes.add(form1);
+    testDiv.append(form1);
     var form2 = new FormElement();
-    testDiv.nodes.add(form2);
+    testDiv.append(form2);
 
     var el1 = new InputElement();
-    form1.nodes.add(el1);
+    form1.append(el1);
     el1.type = 'radio';
     el1.name = RADIO_GROUP_NAME;
     el1.bind('checked', model, 'val1');
 
     var el2 = new InputElement();
-    form1.nodes.add(el2);
+    form1.append(el2);
     el2.type = 'radio';
     el2.name = RADIO_GROUP_NAME;
     el2.bind('checked', model, 'val2');
 
     var el3 = new InputElement();
-    form2.nodes.add(el3);
+    form2.append(el3);
     el3.type = 'radio';
     el3.name = RADIO_GROUP_NAME;
     el3.bind('checked', model, 'val3');
 
     var el4 = new InputElement();
-    form2.nodes.add(el4);
+    form2.append(el4);
     el4.type = 'radio';
     el4.name = RADIO_GROUP_NAME;
     el4.bind('checked', model, 'val4');
@@ -310,11 +310,11 @@
 
   test('BindToChecked', () {
     var div = new DivElement();
-    testDiv.nodes.add(div);
+    testDiv.append(div);
     var child = new DivElement();
-    div.nodes.add(child);
+    div.append(child);
     var input = new InputElement();
-    child.nodes.add(input);
+    child.append(input);
     input.type = 'checkbox';
 
     var model = toSymbolMap({'a': {'b': false}});
@@ -330,8 +330,8 @@
   test('MultipleReferences', () {
     var el = new DivElement();
     var template = new Element.html('<template bind>');
-    template.content.nodes.add(el);
-    testDiv.nodes.add(template);
+    template.content.append(el);
+    testDiv.append(template);
 
     var model = toSymbolMap({'foo': 'bar'});
     el.attributes['foo'] = '{{foo}} {{foo}}';
diff --git a/tests/html/event_test.dart b/tests/html/event_test.dart
index df0fe1c..29ceea5 100644
--- a/tests/html/event_test.dart
+++ b/tests/html/event_test.dart
@@ -144,7 +144,7 @@
   test('DOMMutationEvent', () {
     var div = new DivElement();
     div.on['DOMSubtreeModified'].add(expectAsync1((DOMMutationEvent e) {}));
-    div.nodes.add(new SpanElement());
+    div.append(new SpanElement());
   });
 
   // Issue 1005.
diff --git a/tests/html/events_test.dart b/tests/html/events_test.dart
index 4e22018..8451c893d 100644
--- a/tests/html/events_test.dart
+++ b/tests/html/events_test.dart
@@ -29,7 +29,7 @@
   test('EventTarget', () {
     Element element = new Element.tag('test');
     element.id = 'eventtarget';
-    window.document.body.nodes.add(element);
+    window.document.body.append(element);
 
     int invocationCounter = 0;
     void handler(Event e) {
diff --git a/tests/html/html.status b/tests/html/html.status
index e539b1d..3fdbc52 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -24,6 +24,12 @@
 indexeddb_4_test: Pass, Timeout, Slow # Issue: http://dartbug.com/9437
 async_test: Pass, Fail # timers test fails on ie10.
 
+[ $compiler == dart2js && ( $runtime == ie9 || $runtime == ie10 ) ]
+worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
+
+[ $compiler == dart2js && ( $runtime == ff ) ]
+worker_api_test: Fail # Requires Firefox 21.
+
 [ $compiler == dart2js && $runtime == safari ]
 url_test: Fail # Issue 10096
 
@@ -46,6 +52,7 @@
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) ]
 request_animation_frame_test: Skip   # drt hangs; requestAnimationFrame not implemented
+worker_api_test: Fail # http://dartbug.com/10223
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows]
 websql_test: Skip # Issue 4941: stderr contains a backtrace.
@@ -113,6 +120,7 @@
 webgl_1_test/supported: Fail
 websql_test/supported: Fail
 xhr_test/supported_HttpRequestProgressEvent: Fail
+xhr_test/supported_overrideMimeType: Fail
 xsltprocessor_test/supported: Fail
 
 [ $runtime == ie9 ]
@@ -219,6 +227,7 @@
 xhr_test/supported_HttpRequestProgressEvent: Fail
 xhr_test/supported_onLoadEnd: Fail
 xhr_test/supported_onProgress: Fail
+xhr_test/supported_overrideMimeType: Fail
 xsltprocessor_test/supported: Fail
 
 [ $runtime == safari ]
@@ -370,3 +379,6 @@
 postmessage_structured_test: Skip  # Test cannot run under CSP restrictions (times out).
 safe_dom_test: Skip                # Test cannot run under CSP restrictions (times out).
 shadow_dom_layout_test: Fail, OK   # Test cannot run under CSP restrictions.
+
+[ $compiler == dartanalyzer ]
+path_observer_test: Fail
diff --git a/tests/html/htmlcollection_test.dart b/tests/html/htmlcollection_test.dart
index e5e20cd..296f30b 100644
--- a/tests/html/htmlcollection_test.dart
+++ b/tests/html/htmlcollection_test.dart
@@ -28,7 +28,7 @@
 </div>
 <div id='emptyDiv'></div>
 """;
-    document.body.nodes.add(element);
+    document.body.append(element);
     return element;
   }
 
diff --git a/tests/html/htmlelement_test.dart b/tests/html/htmlelement_test.dart
index c18ba67..df2704d 100644
--- a/tests/html/htmlelement_test.dart
+++ b/tests/html/htmlelement_test.dart
@@ -9,7 +9,7 @@
     Element element = new Element.tag('div');
     element.id = 'test';
     element.innerHtml = 'Hello World';
-    document.body.nodes.add(element);
+    document.body.append(element);
 
     element = document.query('#test');
     expect(element.innerHtml, 'Hello World');
@@ -19,10 +19,10 @@
     Element table = new Element.tag('table');
 
     TableRowElement row = new Element.tag('tr');
-    table.nodes.add(row);
+    table.append(row);
 
-    row.nodes.add(new Element.tag('td'));
-    row.nodes.add(new Element.tag('td'));
+    row.append(new Element.tag('td'));
+    row.append(new Element.tag('td'));
 
     expect(row.cells.length, 2);
 
diff --git a/tests/html/instance_of_test.dart b/tests/html/instance_of_test.dart
index 2d6069d..6e70809 100644
--- a/tests/html/instance_of_test.dart
+++ b/tests/html/instance_of_test.dart
@@ -9,7 +9,7 @@
   canvas = new Element.tag('canvas');
   canvas.attributes['width'] = '100';
   canvas.attributes['height'] = '100';
-  document.body.nodes.add(canvas);
+  document.body.append(canvas);
 
   var isCanvasRenderingContext = predicate((x) => x is CanvasRenderingContext,
       'is a CanvasRenderingContext');
diff --git a/tests/html/js_interop_1_test.dart b/tests/html/js_interop_1_test.dart
index 3bf0951..7439992 100644
--- a/tests/html/js_interop_1_test.dart
+++ b/tests/html/js_interop_1_test.dart
@@ -11,7 +11,7 @@
   final script = new ScriptElement();
   script.type = 'text/javascript';
   script.innerHtml = code;
-  document.body.nodes.add(script);
+  document.body.append(script);
 }
 
 main() {
diff --git a/tests/html/js_interop_2_test.dart b/tests/html/js_interop_2_test.dart
index 46a44de..96e6a40 100644
--- a/tests/html/js_interop_2_test.dart
+++ b/tests/html/js_interop_2_test.dart
@@ -12,7 +12,7 @@
   final script = new ScriptElement();
   script.type = 'text/javascript';
   script.innerHtml = code;
-  document.body.nodes.add(script);
+  document.body.append(script);
 }
 
 var isolateTest = """
diff --git a/tests/html/js_interop_3_test.dart b/tests/html/js_interop_3_test.dart
index 390c687..4871b96 100644
--- a/tests/html/js_interop_3_test.dart
+++ b/tests/html/js_interop_3_test.dart
@@ -13,7 +13,7 @@
   final script = new ScriptElement();
   script.type = 'text/javascript';
   script.innerHtml = code;
-  document.body.nodes.add(script);
+  document.body.append(script);
 }
 
 var jsToDart = """
diff --git a/tests/html/mutationobserver_test.dart b/tests/html/mutationobserver_test.dart
index 9710310..f73f2a5 100644
--- a/tests/html/mutationobserver_test.dart
+++ b/tests/html/mutationobserver_test.dart
@@ -67,8 +67,8 @@
             mutationCallback(2, orderedEquals([div1, div2])));
         mutationObserver.observe(container, childList: true);
 
-        container.nodes.add(div1);
-        container.nodes.add(div2);
+        container.append(div1);
+        container.append(div2);
       }, expectation);
     });
 
@@ -81,8 +81,8 @@
             new MutationObserver(mutationCallback(1, orderedEquals([div1])));
         mutationObserver.observe(container, childList: true);
 
-        container.nodes.add(div1);
-        div1.nodes.add(div2);
+        container.append(div1);
+        div1.append(div2);
       }, expectation);
     });
 
@@ -95,8 +95,8 @@
             mutationCallback(2, orderedEquals([div1, div2])));
         mutationObserver.observe(container, childList: true, subtree: true);
 
-        container.nodes.add(div1);
-        div1.nodes.add(div2);
+        container.append(div1);
+        div1.append(div2);
       }, expectation);
     });
 
diff --git a/tests/html/native_gc_test.dart b/tests/html/native_gc_test.dart
index 8ed06bb..14ad75d 100644
--- a/tests/html/native_gc_test.dart
+++ b/tests/html/native_gc_test.dart
@@ -38,7 +38,7 @@
 
     Element testDiv = new DivElement();
     testDiv.id = '#TestDiv';
-    document.body.nodes.add(testDiv);
+    document.body.append(testDiv);
     window.onMessage.listen((e) {
       if (e.data == message) testDiv.click();
     });
diff --git a/tests/html/node_bindings_test.dart b/tests/html/node_bindings_test.dart
index 6787ec0..fd08fd4 100644
--- a/tests/html/node_bindings_test.dart
+++ b/tests/html/node_bindings_test.dart
@@ -25,7 +25,7 @@
   var testDiv;
 
   setUp(() {
-    document.body.nodes.add(testDiv = new DivElement());
+    document.body.append(testDiv = new DivElement());
   });
 
   tearDown(() {
@@ -135,7 +135,7 @@
 
   test('Checkbox Input', () {
     var input = new InputElement();
-    testDiv.nodes.add(input);
+    testDiv.append(input);
     input.type = 'checkbox';
     var model = toSymbolMap({'x': true});
     input.bind('checked', model, 'x');
diff --git a/tests/html/node_test.dart b/tests/html/node_test.dart
index c8a009c..1070554 100644
--- a/tests/html/node_test.dart
+++ b/tests/html/node_test.dart
@@ -118,6 +118,17 @@
       expect(makeNodeWithChildren().nodes, isNodeList);
     });
 
+    test('indexer', () {
+      var node = new DivElement();
+      expect(() {
+        node.nodes[0];
+      }, throwsRangeError);
+
+      expect(() {
+        node.nodes[-1];
+      }, throwsRangeError);
+    });
+
     test('first', () {
       var node = makeNodeWithChildren();
       expect(node.nodes.first, isText);
@@ -324,28 +335,90 @@
     });
   });
 
-  group('_NodeList', () {
+  group('NodeList', () {
+    // Tests for methods on the DOM class 'NodeList'.
+    //
+    // There are two interesting things that are checked here from the viewpoint
+    // of the dart2js implementation of a 'native' class:
+    //
+    //   1. Some methods are implementated from by 'Object' or 'Interceptor';
+    //      some of these tests simply check that a method can be called.
+    //   2. Some methods are implemented by mixins.
+
     List<Node> makeNodeList() =>
-      makeNodeWithChildren().nodes.where((_) => true).toList();
+        (new Element.html("<div>Foo<br/><!--baz--><br/><br/></div>"))
+        .$dom_getElementsByTagName('br');
+    // Our WebKit-derived bindings declare getElementsByTagName as returning
+    // NodeList.
+    //
+    // WebKit browsers returns NodeList.
+    // Firefox and IE return HtmlCollection.
+    // This is messed-up since the two types are disjoint.  We could make
+    // HtmlCollection extend NodeList but we would require better optimizations
+    // to recognize when NodeList_methods can be used.
+
+    test('trueNodeList', () {
+      var nodes = makeNodeList();
+      expect(nodes is NodeList || nodes is HtmlCollection, true);
+    });
+
+    test('hashCode', () {
+      var nodes = makeNodeList();
+      var hash = nodes.hashCode;
+      final int N = 1000;
+      int matchCount = 0;
+      for (int i = 0; i < N; i++) {
+        if (makeNodeList().hashCode == hash) matchCount++;
+      }
+      expect(matchCount, lessThan(N));
+    });
+
+    test('operator==', () {
+      var a = [makeNodeList(), makeNodeList(), null];
+      for (int i = 0; i < a.length; i++) {
+        for (int j = 0; j < a.length; j++) {
+          expect(i == j,  a[i] == a[j]);
+        }
+      }
+    });
+
+    test('runtimeType', () {
+      var nodes1 = makeNodeList();
+      var nodes2 = makeNodeList();
+      var type1 = nodes1.runtimeType;
+      var type2 = nodes2.runtimeType;
+      expect(type1 == type2, true);
+      String name = '$type1';
+      if (name.length > 3) {
+        expect(name.contains('NodeList') || name.contains('HtmlCollection'),
+               true);
+      }
+    });
 
     test('first', () {
       var nodes = makeNodeList();
-      expect(nodes.first, isText);
+      expect(nodes.first, isBRElement);
+    });
+
+    test('last', () {
+      var nodes = makeNodeList();
+      expect(nodes.last, isBRElement);
     });
 
     test('where', () {
       var filtered = makeNodeList().where((n) => n is BRElement).toList();
-      expect(filtered.length, 1);
+      expect(filtered.length, 3);
       expect(filtered[0], isBRElement);
       expect(filtered, isNodeList);
     });
 
     test('sublist', () {
       var range = makeNodeList().sublist(1, 3);
-      expect(range, isNodeList);
+      expect(range.length, 2);
       expect(range[0], isBRElement);
-      expect(range[1], isComment);
+      expect(range[1], isBRElement);
     });
+
   });
 
   group('iterating', () {
diff --git a/tests/html/postmessage_structured_test.dart b/tests/html/postmessage_structured_test.dart
index e56e3b1..0ff9665 100644
--- a/tests/html/postmessage_structured_test.dart
+++ b/tests/html/postmessage_structured_test.dart
@@ -14,7 +14,7 @@
   final script = new ScriptElement();
   script.type = 'text/javascript';
   script.innerHtml = code;
-  document.body.nodes.add(script);
+  document.body.append(script);
 }
 
 main() {
diff --git a/tests/html/queryall_test.dart b/tests/html/queryall_test.dart
index 6ebce45..7b910c5 100644
--- a/tests/html/queryall_test.dart
+++ b/tests/html/queryall_test.dart
@@ -17,7 +17,7 @@
 
   var div = new DivElement();
   div.id = 'test';
-  document.body.nodes.add(div);
+  document.body.append(div);
 
   div.nodes.addAll([
       new DivElement(),
diff --git a/tests/html/shadow_dom_layout_test.dart b/tests/html/shadow_dom_layout_test.dart
index 5a1d6b8..82705bc 100644
--- a/tests/html/shadow_dom_layout_test.dart
+++ b/tests/html/shadow_dom_layout_test.dart
@@ -21,12 +21,12 @@
 
   // assemble DOM
   var sRoot = div.createShadowRoot();
-  sRoot.nodes.add(new Element.html('<content select=".foo"></content>'));
-  sRoot.nodes.add(redbox);
-  sRoot.nodes.add(new Element.tag('content'));
+  sRoot.append(new Element.html('<content select=".foo"></content>'));
+  sRoot.append(redbox);
+  sRoot.append(new Element.tag('content'));
 
-  div.nodes.add(bluebox);
-  div.nodes.add(greenbox);
+  div.append(bluebox);
+  div.append(greenbox);
 }
 
 DivElement _colorBox(String color, int width, int height) {
diff --git a/tests/html/shadow_dom_test.dart b/tests/html/shadow_dom_test.dart
index 7f6112e..78b62b5 100644
--- a/tests/html/shadow_dom_test.dart
+++ b/tests/html/shadow_dom_test.dart
@@ -28,11 +28,11 @@
       div2 = new DivElement();
       div1.classes.add('foo');
       shadowRoot = div2.createShadowRoot();
-      shadowRoot.nodes.add(paragraph1);
-      shadowRoot.nodes.add(new ContentElement());
-      div2.nodes.add(paragraph2);
-      document.body.nodes.add(div1);
-      document.body.nodes.add(div2);
+      shadowRoot.append(paragraph1);
+      shadowRoot.append(new ContentElement());
+      div2.append(paragraph2);
+      document.body.append(div1);
+      document.body.append(div2);
     }
 
     var expectation = ShadowRoot.supported ? returnsNormally : throws;
diff --git a/tests/html/svg_test.dart b/tests/html/svg_test.dart
index ee327bf..156f379 100644
--- a/tests/html/svg_test.dart
+++ b/tests/html/svg_test.dart
@@ -16,7 +16,7 @@
 
     test('simpleRect', () {
       var div = new Element.tag('div');
-      document.body.nodes.add(div);
+      document.body.append(div);
       div.innerHtml = r'''
 <svg id='svg1' width='200' height='100'>
 <rect id='rect1' x='10' y='20' width='130' height='40' rx='5'fill='blue'></rect>
@@ -58,7 +58,7 @@
 <rect id='rect1' x='10' y='20' width='130' height='40' rx='5'fill='blue'></rect>
 </svg>
 ''';
-      document.body.nodes.add(element);
+      document.body.append(element);
       return element;
     }
 
@@ -112,7 +112,7 @@
 <rect id='rect1' x='10' y='20' width='130' height='40' rx='5'fill='blue'></rect>
 </svg>
 ''';
-    document.body.nodes.add(element);
+    document.body.append(element);
     return element;
   }
 
diff --git a/tests/html/template_element_test.dart b/tests/html/template_element_test.dart
index c34aa76..d71f854 100644
--- a/tests/html/template_element_test.dart
+++ b/tests/html/template_element_test.dart
@@ -28,7 +28,7 @@
   var testDiv;
 
   setUp(() {
-    document.body.nodes.add(testDiv = new DivElement());
+    document.body.append(testDiv = new DivElement());
   });
 
   tearDown(() {
@@ -39,7 +39,7 @@
   createTestHtml(s) {
     var div = new DivElement();
     div.innerHtml = s;
-    testDiv.nodes.add(div);
+    testDiv.append(div);
 
     for (var node in div.queryAll('*')) {
       if (node.isTemplate) TemplateElement.decorate(node);
@@ -52,7 +52,7 @@
     var div = new DivElement();
     var root = div.createShadowRoot();
     root.innerHtml = s;
-    testDiv.nodes.add(div);
+    testDiv.append(div);
 
     for (var node in root.queryAll('*')) {
       if (node.isTemplate) TemplateElement.decorate(node);
@@ -434,7 +434,7 @@
     var t = new Element.tag('template');
     TemplateElement.decorate(t);
 
-    document.body.nodes.add(t);
+    document.body.append(t);
     expect(t.getComputedStyle().display, 'none');
 
     t.remove();
@@ -1320,6 +1320,24 @@
     }
   });
 
+  test('BindShadowDOM bindModel', () {
+    if (ShadowRoot.supported) {
+      var root = createShadowTestHtml('Hi {{ name }}');
+      var model = toSymbolMap({'name': 'Leela'});
+      TemplateElement.bindModel(root, model);
+      deliverChangeRecords();
+      expect(root.text, 'Hi Leela');
+    }
+  });
+
+  test('bindModel to polyfilled shadow root', () {
+    var root = createTestHtml('Hi {{ name }}');
+    var model = toSymbolMap({'name': 'Leela'});
+    TemplateElement.bindModel(root, model);
+    deliverChangeRecords();
+    expect(root.text, 'Hi Leela');
+  });
+
   // https://github.com/toolkitchen/mdv/issues/8
   test('UnbindingInNestedBind', () {
     var div = createTestHtml(
diff --git a/tests/html/window_open_test.dart b/tests/html/window_open_test.dart
index 23baef4..0f65ec9 100644
--- a/tests/html/window_open_test.dart
+++ b/tests/html/window_open_test.dart
@@ -9,7 +9,7 @@
   evaluateJavaScript(code) {
     final scriptTag = new Element.tag('script');
     scriptTag.innerHtml = code;
-    document.body.nodes.add(scriptTag);
+    document.body.append(scriptTag);
   }
   evaluateJavaScript('(testRunner || layoutTestController).setCanOpenWindows()');
 
diff --git a/tests/html/worker_api_test.dart b/tests/html/worker_api_test.dart
new file mode 100644
index 0000000..947c918
--- /dev/null
+++ b/tests/html/worker_api_test.dart
@@ -0,0 +1,31 @@
+// 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:html';
+import 'dart:isolate';
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+worker() {
+  port.receive((String uri, SendPort replyTo) {
+    try {
+      var url = Url.createObjectUrl(new Blob([''], 'application/javascript'));
+      Url.revokeObjectUrl(url);
+      replyTo.send('Hello from Worker');
+    } catch (e) {
+      replyTo.send('Error: $e');
+    }
+    port.close();
+  });
+}
+
+main() {
+  useHtmlConfiguration();
+
+  test('Use Worker API in Worker', () {
+    spawnFunction(worker).call('').then(
+        expectAsync1((reply) => expect(reply, equals('Hello from Worker'))));
+  });
+}
diff --git a/tests/html/xhr_test.dart b/tests/html/xhr_test.dart
index 9d44746..484b2e7 100644
--- a/tests/html/xhr_test.dart
+++ b/tests/html/xhr_test.dart
@@ -51,6 +51,12 @@
     });
   });
 
+  group('supported_overrideMimeType', () {
+    test('supported', () {
+      expect(HttpRequest.supportsOverrideMimeType, isTrue);
+    });
+  });
+
   group('xhr', () {
     test('XHR No file', () {
       HttpRequest xhr = new HttpRequest();
@@ -145,7 +151,8 @@
 
     test('XHR.request responseType arraybuffer', () {
       if (Platform.supportsTypedData) {
-        HttpRequest.request(url, responseType: 'arraybuffer').then(
+        HttpRequest.request(url, responseType: 'arraybuffer',
+          requestHeaders: {'Content-Type': 'text/xml'}).then(
           expectAsync1((xhr) {
             expect(xhr.status, equals(200));
             var byteBuffer = xhr.response;
@@ -163,6 +170,15 @@
         expect(event is HttpRequestProgressEvent, isTrue);
       }, expectation);
     });
+
+    test('overrideMimeType', () {
+      var expectation =
+          HttpRequest.supportsOverrideMimeType ? returnsNormally : throws;
+
+      expect(() {
+        HttpRequest.request(url, mimeType: 'application/binary');
+      }, expectation);
+    });
   });
 
   group('xhr_requestBlob', () {
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index b0cd54b..398930c 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -11,8 +11,10 @@
 compute_this_script_browser_stream_test: Skip # browser specific test
 ports_compilation_browser_test: Skip # browser specific test
 unresolved_ports_negative_test: Skip # See Issue 6839
-global_error_handler_test: Fail # See Issue 9013.
+global_error_handler_test: Fail, Pass # See Issue 9013.
 global_error_handler_stream_test: Fail # See Issue 9013.
+isolate_stress_test: Fail # TODO(ahe): This should be able to pass when we have wrapper-less tests.
+
 
 [ $runtime == vm && $system == windows ]
 timer_test: Pass, Fail # See Issue 5133
@@ -52,6 +54,9 @@
 [ $compiler == dart2js && $browser ]
 illegal_msg_stream_test: Fail, Pass # Issue 6750
 
+[ $compiler == dart2js && $runtime == drt ]
+unresolved_ports_negative_test: Pass, Crash # Issue 10613
+
 [ $compiler == dart2js ]
 serialization_test: Fail # Tries to access class TestingOnly declared in isolate_patch.dart
 illegal_msg_test: Fail # Issue 6750
diff --git a/tests/language/closure_side_effect_test.dart b/tests/language/closure_side_effect_test.dart
new file mode 100644
index 0000000..7a68ac8
--- /dev/null
+++ b/tests/language/closure_side_effect_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+var b;
+var a = () {
+  b = 42;
+};
+
+var c = [new C()];
+
+class C {
+  nonInlinable1() {
+    a();
+  }
+
+  nonInlinable2() {
+    var a = () { b = 42; };
+    a();
+  }
+}
+
+testClosureInStaticField() {
+  var temp = c[0];
+  Expect.isNull(b);
+  temp.nonInlinable1();
+  Expect.equals(42, b);
+  b = null;
+}
+
+testLocalClosure() {
+  var temp = c[0];
+  Expect.isNull(b);
+  temp.nonInlinable2();
+  Expect.equals(42, b);
+}
+
+main() {
+  testClosureInStaticField();
+  testLocalClosure();
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 6808a65..bfda549 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -670,18 +670,16 @@
 default_factory2_test/01: fail
 default_implementation2_test: fail
 duplicate_constructor_test/01: fail
-duplicate_export_negative_test: fail
 dynamic2_test/00: fail
 dynamic_field_test: fail
+export_cyclic_test: fail
 f_bounded_quantification_test/01: fail
 f_bounded_quantification_test/02: fail
 factory1_test/00: skip
 factory1_test/01: skip
-factory2_negative_test: fail
 factory2_test: fail
 factory5_test/00: fail
 factory_implementation_test/00: skip
-factory_negative_test: fail
 factory_redirection2_test/01: fail
 factory_redirection_test/04: fail
 factory_redirection_test/07: fail
@@ -747,9 +745,6 @@
 list_literal_syntax_test/05: fail
 map_literal1_negative_test: fail
 map_literal3_test: fail
-method_override2_test/00: fail
-method_override2_test/01: fail
-method_override2_test/02: fail
 method_override2_test/03: fail
 mixin_illegal_constructor_test/13: fail
 mixin_illegal_constructor_test/14: fail
@@ -823,7 +818,6 @@
 static_final_field_negative_test: fail
 string_interpolate1_negative_test: fail
 string_interpolate2_negative_test: fail
-string_interpolation1_negative_test: fail
 string_interpolation2_negative_test: fail
 string_interpolation3_negative_test: fail
 string_interpolation4_negative_test: fail
diff --git a/tests/language/optimized_constant_array_string_access_test.dart b/tests/language/optimized_constant_array_string_access_test.dart
index d8f6a80..8b63df3 100644
--- a/tests/language/optimized_constant_array_string_access_test.dart
+++ b/tests/language/optimized_constant_array_string_access_test.dart
@@ -19,15 +19,25 @@
 
 
 int testConstantArrayAndIndexAt() {
-  int test(b) {
+  int testPositive(b) {
     var a = const [1,2,3,4];
     if (b) return a[400];
     return a[2];
   }
 
-  Expect.throws(() => test(true));
-  for (int i = 0; i < 10000; i++) test(false);
-  Expect.throws(() => test(true));
+  int testNegative(b) {
+    var a = const [1,2,3,4];
+    if (b) return a[-1];
+    return a[2];
+  }
+
+  Expect.throws(() => testPositive(true));
+  for (int i = 0; i < 10000; i++) testPositive(false);
+  Expect.throws(() => testPositive(true));
+
+  Expect.throws(() => testNegative(true));
+  for (int i = 0; i < 10000; i++) testNegative(false);
+  Expect.throws(() => testNegative(true));
 }
 
 
diff --git a/tests/language/try_catch2_test.dart b/tests/language/try_catch2_test.dart
index fea2de8..9de57c0 100644
--- a/tests/language/try_catch2_test.dart
+++ b/tests/language/try_catch2_test.dart
@@ -61,5 +61,7 @@
 }
 
 main() {
-  TryCatch2Test.testMain();
+  for (var i = 0; i < 2000; i++) {
+    TryCatch2Test.testMain();
+  }
 }
diff --git a/tests/language/try_catch3_test.dart b/tests/language/try_catch3_test.dart
index d679a4b..feba2b3 100644
--- a/tests/language/try_catch3_test.dart
+++ b/tests/language/try_catch3_test.dart
@@ -113,5 +113,7 @@
 }
 
 main() {
-  TryCatchTest.testMain();
+  for (var i = 0; i < 2000; i++) {
+    TryCatchTest.testMain();
+  }
 }
diff --git a/tests/language/try_catch4_test.dart b/tests/language/try_catch4_test.dart
index 9ee40f5..d5e9809 100644
--- a/tests/language/try_catch4_test.dart
+++ b/tests/language/try_catch4_test.dart
@@ -175,7 +175,7 @@
   }
 }
 
-main() {
+main_test() {
   a = 0;
   Expect.isTrue(foo1());
   a = 0;
@@ -195,3 +195,9 @@
   a = 0;
   Expect.isTrue(foo9());
 }
+
+main() {
+  for (var i = 0; i < 2000; i++) {
+    main_test();
+  }
+}
diff --git a/tests/language/try_catch5_test.dart b/tests/language/try_catch5_test.dart
index 1b0e421..2d9b557 100644
--- a/tests/language/try_catch5_test.dart
+++ b/tests/language/try_catch5_test.dart
@@ -30,6 +30,8 @@
 }
 
 main() {
-  a = 0;
-  Expect.isTrue(foo1());
+  for (var i = 0; i < 2000; i++) {
+    a = 0;
+    Expect.isTrue(foo1());
+  }
 }
diff --git a/tests/language/try_catch_optimized1_test.dart b/tests/language/try_catch_optimized1_test.dart
new file mode 100644
index 0000000..cffcbc2
--- /dev/null
+++ b/tests/language/try_catch_optimized1_test.dart
@@ -0,0 +1,299 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+maythrow(x) {
+  if (x == null) throw 42;
+  return 99;
+}
+
+
+f1(x) {
+  var result = 123;
+  try {
+    result = maythrow(x);
+    if (result > 100) throw 42;
+  } catch(e) {
+    Expect.equals(result, 123);
+    Expect.equals(42, e);
+    result = 0;
+  }
+  return result;
+}
+
+
+class A {
+  maythrow(x) {
+    if (x == null) throw 42;
+    return 99;
+  }
+}
+
+
+f2(x) {
+  var result = 123;
+  var a = new A();
+  try {
+    result++;
+    result = a.maythrow(x);
+  } catch(e) {
+    Expect.equals(124, result);
+    result = x;
+  }
+  return result;
+}
+
+
+f3(x, y) {
+  var result = 123;
+  var a = new A();
+  try {
+    result++;
+    result = a.maythrow(x);
+  } catch(e) {
+    result = y + 1; // Deopt on overflow
+  }
+  return result;
+}
+
+
+f4(x) {
+  try {
+    maythrow(x);
+  } catch(e) {
+    check_f4(e, "abc");
+  }
+}
+
+check_f4(e, s) {
+  if (e != 42) throw "ERROR";
+  if (s != "abc") throw "ERROR";
+}
+
+
+f5(x) {
+  try {
+    maythrow(x);
+  } catch(e) {
+    check_f5(e, "abc");
+  }
+
+  try {
+    maythrow(x);
+  } catch(e) {
+    check_f5(e, "abc");
+  }
+}
+
+check_f5(e, s) {
+  if (e != 42) throw "ERROR";
+  if (s != "abc") throw "ERROR";
+}
+
+
+f6(x, y) {
+  var a = x;
+  var b = y;
+  var c = 123;
+  check_f6(42, null, 1, 123, null, 1);
+  try {
+    maythrow(x);
+  } catch(e) {
+    check_f6(e, a, b, c, x, y);
+  }
+}
+
+check_f6(e, a, b, c, x, y) {
+  if (e != 42) throw "ERROR";
+  if (a != null) throw "ERROR";
+  if (b != 1) throw "ERROR";
+  if (c != 123) throw "ERROR";
+  if (x != null) throw "ERROR";
+  if (y != 1) throw "ERROR";
+}
+
+
+bool f7(String str) {
+  double d = double.parse(str);
+  var t = d;
+  try {
+    var a = d.toInt();
+    return false;
+  } on UnsupportedError catch (e) {
+    Expect.equals(true, identical(t, d));
+    return true;
+  }
+}
+
+
+f8(x, [a = 3, b = 4]) {
+  var c = 123;
+  var y = a;
+  try {
+    maythrow(x);
+  } catch(e, s) {
+    check_f8(e, s, a, b, c, x, y);
+  }
+}
+
+check_f8(e, s, a, b, c, x, y) {
+  if (e != 42) throw "ERROR";
+  if (s is! StackTrace) throw "ERROR";
+  if (a != 3)  { print(a); throw "ERROR"; }
+  if (b != 4) throw "ERROR";
+  if (c != 123) throw "ERROR";
+  if (x != null) throw "ERROR";
+  if (y != a) throw "ERROR";
+}
+
+
+f9(x, [a = 3, b = 4]) {
+  var c = 123;
+  var y = a;
+  try {
+    if (x < a) maythrow(null);
+    maythrow(x);
+  } catch(e, s) {
+    check_f9(e, s, a, b, c, x, y);
+  }
+}
+
+
+check_f9(e, s, a, b, c, x, y) {
+  if (e != 42) throw "ERROR";
+  if (s is! StackTrace) throw "ERROR";
+  if (a != 3)  { print(a); throw "ERROR"; }
+  if (b != 4) throw "ERROR";
+  if (c != 123) throw "ERROR";
+  if (x != null) throw "ERROR";
+  if (y != a) throw "ERROR";
+}
+
+
+f10(x, y) {
+  var result = 123;
+  try {
+    result = maythrow(x);
+  } catch(e) {
+    Expect.equals(123, result);
+    Expect.equals(0.5, y / 2.0);
+    result = 0;
+  }
+  return result;
+}
+
+
+f11(x) {
+  var result = 123;
+  var tmp = x;
+  try {
+    result = maythrow(x);
+    if (result > 100) throw 42;
+  } catch(e, s) {
+    Expect.equals(123, result);
+    Expect.equals(true, identical(tmp, x));
+    Expect.equals(true, s is StackTrace);
+    result = 0;
+  }
+  return result;
+}
+
+
+f12([x = null]) {
+  try {
+    maythrow(x);
+  } catch(e) {
+    check_f12(e, x);
+  }
+}
+
+check_f12(e, x) {
+  if (e != 42) throw "ERROR";
+  if (x != null) throw "ERROR";
+}
+
+
+f13(x) {
+  var result = 123;
+  try {
+    try {
+      result = maythrow(x);
+      if (result > 100) throw 42;
+    } catch(e) {
+      Expect.equals(123, result);
+      result = 0;
+    }
+    maythrow(x);
+  } catch(e) {
+    result++;
+  }
+  return result;
+}
+
+
+main() {
+  for (var i=0; i<10000; i++) f1("abc");
+  Expect.equals(99, f1("abc"));
+  Expect.equals(0, f1(null));
+
+  for (var i=0; i<10000; i++) f2("abc");
+  Expect.equals(99, f2("abc"));
+  Expect.equals(null, f2(null));
+
+  f3("123", 0);
+  for (var i=0; i<10000; i++) f3(null, 0);
+  Expect.equals(99, f3("123", 0));
+  Expect.equals(0x40000000, f3(null, 0x3fffffff));
+
+  f4(null);
+  for (var i=0; i<10000; i++) f4(123);
+  f4(null);
+
+  f5(null);
+  for (var i=0; i<10000; i++) f5(123);
+  f5(null);
+
+  f6(null, 1);
+  for (var i=0; i<10000; i++) f6(123, 1);
+  f6(null, 1);
+
+  f7("1.2");
+  f7("Infinity");
+  f7("-Infinity");
+  for (var i=0; i<10000; i++) f7("1.2");
+  Expect.equals(false, f7("1.2"));
+  Expect.equals(true, f7("Infinity"));
+  Expect.equals(true, f7("-Infinity"));
+  Expect.equals(false, f7("123456789012345"));  // Deopt.
+  for (var i=0; i<10000; i++) f7("123456789012345");  
+  Expect.equals(true, f7("Infinity"));
+  Expect.equals(true, f7("-Infinity"));
+
+  for (var i=0; i<10000; i++) f8(null);
+  f8(null);
+
+  f9(5);
+  f9(5.0);
+  for (var i=0; i<10000; i++) f9(3);
+  f9(3);
+
+  var y = 1.0;
+  Expect.equals(0, f10(null, y));
+  for (var i = 0; i < 10000; i++) f10("abc", y);
+  Expect.equals(99, f10("abc", y));
+  Expect.equals(0, f10(null, y));
+
+  for (var i=0; i<10000; i++) f11("abc");
+  Expect.equals(99, f11("abc"));
+  Expect.equals(0, f11(null));
+
+  for (var i=0; i<10000; i++) f12(null);
+  f12(null);
+
+  f13(null);
+  for (var i=0; i<10000; i++) f13("abc");
+  Expect.equals(99, f13("abc"));
+  Expect.equals(1, f13(null));
+}
diff --git a/tests/language/try_catch_test.dart b/tests/language/try_catch_test.dart
index ff3d6d6..73c7282 100644
--- a/tests/language/try_catch_test.dart
+++ b/tests/language/try_catch_test.dart
@@ -151,5 +151,7 @@
 }
 
 main() {
-  TryCatchTest.testMain();
+  for (var i = 0; i < 2000; i++) {
+    TryCatchTest.testMain();
+  }
 }
diff --git a/tests/lib/typed_data/float32x4_unbox_phi_test.dart b/tests/lib/typed_data/float32x4_unbox_phi_test.dart
new file mode 100644
index 0000000..008d9c9
--- /dev/null
+++ b/tests/lib/typed_data/float32x4_unbox_phi_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--deoptimization_counter_threshold=1000
+
+// Library tag to be able to run in html test framework.
+library float32x4_unbox_regress_test;
+
+import 'package:expect/expect.dart';
+import 'dart:typed_data';
+
+double testUnboxPhi(Float32x4List data) {
+  var res = new Float32x4.zero();
+  for (int i = 0; i < data.length; i++) {
+    res += data[i];
+  }
+  return res.x + res.y + res.z + res.w;
+}
+
+main() {
+  Float32x4List list = new Float32x4List(10);
+  Float32List floatList = new Float32List.view(list);
+  for (int i = 0; i < floatList.length; i++) {
+    floatList[i] = i.toDouble();
+  }
+  for (int i = 0; i < 2000; i++) {
+    double r = testUnboxPhi(list);
+    Expect.equals(780.0, r);
+  }
+}
diff --git a/tests/standalone/debugger/closure_debugger_test.dart b/tests/standalone/debugger/closure_debugger_test.dart
new file mode 100644
index 0000000..07eb5ad
--- /dev/null
+++ b/tests/standalone/debugger/closure_debugger_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test forks a second vm process that runs this dart script as
+// a debug target.
+// Run this test with option --wire to see the json messages sent
+// between the processes.
+// Run this test with option --verbose to see the stdout and stderr output
+// of the debug target process.
+
+import "debug_lib.dart";
+
+bar(x) {
+  print(x);
+}
+
+main() {
+  if (RunScript(testScript)) return;
+  print("Hello from debuggee");
+  var f = bar;
+  f("closure call");
+  bar(12);
+}
+
+
+// Expected debugger events and commands.
+var testScript = [
+  MatchFrame(0, "main"),  // Top frame in trace is function "main".
+  SetBreakpoint(22),      // Set breakpoint a line 22, at the closure call.
+  Resume(),
+  MatchFrame(0, "main"),  // Should be at closure call.
+  StepInto(),
+  MatchFrames(["bar", "main"]),  // Should be in closure function now.
+  StepOut(),
+  MatchFrame(0, "main"),  // Back in main, before static call to bar().
+  SetBreakpoint(15),      // Breakpoint in bar();
+  Resume(),
+  MatchFrames(["bar", "main"]),
+  Resume(),
+];
\ No newline at end of file
diff --git a/tests/standalone/debugger/debug_lib.dart b/tests/standalone/debugger/debug_lib.dart
index 5f5a494..ff51f9b 100644
--- a/tests/standalone/debugger/debug_lib.dart
+++ b/tests/standalone/debugger/debug_lib.dart
@@ -241,6 +241,12 @@
   RunCommand.step() {
     template = {"id": 0, "command": "stepOver", "params": {"isolateId": 0}};
   }
+  RunCommand.stepInto() {
+    template = {"id": 0, "command": "stepInto", "params": {"isolateId": 0}};
+  }
+  RunCommand.stepOut() {
+    template = {"id": 0, "command": "stepOut", "params": {"isolateId": 0}};
+  }
   void send(Debugger debugger) {
     debugger.sendMessage(template);
     debugger.isPaused = false;
@@ -250,7 +256,8 @@
 
 Resume() => new RunCommand.resume();
 Step() => new RunCommand.step();
-
+StepInto() => new RunCommand.stepInto();
+StepOut() => new RunCommand.stepOut();
 
 class SetBreakpointCommand extends Command {
   int line;
diff --git a/tests/standalone/io/file_stat_test.dart b/tests/standalone/io/file_stat_test.dart
new file mode 100644
index 0000000..901b848
--- /dev/null
+++ b/tests/standalone/io/file_stat_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:io FileSystemEntity.Stat().
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+void testStat() {
+  Directory directory = new Directory("").createTempSync();
+  File file = new File.fromPath(new Path(directory.path).append("file"));
+  FileStat nonExistent = FileStat.statSync(file.path);
+  Expect.equals(FileSystemEntityType.NOT_FOUND, nonExistent.type);
+  file.writeAsStringSync("Dart IO library test of FileStat");
+  new Timer(const Duration(seconds: 2), () {
+    file.readAsStringSync();
+    directory.listSync();
+    FileStat fileStat = FileStat.statSync(file.path);
+    Expect.equals(FileSystemEntityType.FILE, fileStat.type);
+    Expect.equals(32, fileStat.size);
+    if (Platform.operatingSystem != 'windows') {
+      Expect.isTrue(fileStat.modified.compareTo(fileStat.accessed) < 0);
+      Expect.isTrue(fileStat.changed.compareTo(fileStat.accessed) < 0);
+    }
+    Expect.equals(6 << 6, fileStat.mode & (6 << 6));  // Mode includes +urw.
+    FileStat directoryStat = FileStat.statSync(directory.path);
+    Expect.equals(FileSystemEntityType.DIRECTORY, directoryStat.type);
+    if (Platform.operatingSystem != 'windows') {
+      Expect.isTrue(
+          directoryStat.modified.compareTo(directoryStat.accessed) < 0);
+      Expect.isTrue(
+          directoryStat.changed.compareTo(directoryStat.accessed) < 0);
+    }
+    Expect.equals(7 << 6, directoryStat.mode & (7 << 6));  // Includes +urwx.
+    directory.deleteSync(recursive: true);
+  });
+}
+
+
+Future testStatAsync() {
+  return new Directory("").createTemp()
+  .then((directory) {
+    File file = new File.fromPath(new Path(directory.path).append("file"));
+    return FileStat.stat(file.path)
+    .then((missingStat) {
+      Expect.equals(FileSystemEntityType.NOT_FOUND, missingStat.type);
+    })
+    .then((_) => file.writeAsString("Dart IO library test of FileStat"))
+    .then((_) => new Future.delayed(const Duration(seconds: 2)))
+    .then((_) => file.readAsString())
+    .then((_) => directory.list().last)
+    .then((_) => FileStat.stat(file.path))
+    .then((FileStat fileStat) {
+      Expect.equals(FileSystemEntityType.FILE, fileStat.type);
+      Expect.equals(32, fileStat.size);
+      if (Platform.operatingSystem != 'windows') {
+        Expect.isTrue(fileStat.modified.compareTo(fileStat.accessed) < 0);
+        Expect.isTrue(fileStat.changed.compareTo(fileStat.accessed) < 0);
+      }
+      Expect.equals(6 << 6, fileStat.mode & (6 << 6));  // Mode includes +urw.
+      return FileStat.stat(directory.path);
+    })
+    .then((FileStat directoryStat) {
+      Expect.equals(FileSystemEntityType.DIRECTORY, directoryStat.type);
+      if (Platform.operatingSystem != 'windows') {
+        Expect.isTrue(
+            directoryStat.modified.compareTo(directoryStat.accessed) < 0);
+        Expect.isTrue(
+            directoryStat.changed.compareTo(directoryStat.accessed) < 0);
+      }
+      Expect.equals(7 << 6, directoryStat.mode & (7 << 6));  // Includes +urwx.
+      return directory.delete(recursive: true);
+    });
+  });
+}
+
+
+void main() {
+  ReceivePort keepAlive = new ReceivePort();
+  testStat();
+  testStatAsync().then((_) => keepAlive.close());
+}
diff --git a/tests/standalone/pow_test.dart b/tests/standalone/pow_test.dart
index 01f7506..575eb08 100644
--- a/tests/standalone/pow_test.dart
+++ b/tests/standalone/pow_test.dart
@@ -85,14 +85,23 @@
 void main() {
   int exp = 0;
   for (int val in expectedResults) {
-    Expect.equals(val, pow(2, exp++));
+    Expect.equals(val, pow(2, exp));
+    Expect.equals(val.toDouble(), pow(2, exp.toDouble()));
+    exp++;
   }
+
   // Optimize it.
   for (int i = 0; i < 8888; i++) {
     pow(2, 3);
+    pow(2.0, 3.0);
   }
   exp = 0;
   for (int val in expectedResults) {
-    Expect.equals(val, pow(2, exp++));
+    Expect.equals(val, pow(2, exp));
+    Expect.equals(val.toDouble(), pow(2, exp.toDouble()));
+    exp++;
   }
+  // Test Bigints.
+  Expect.equals(5559917313492231481, pow(11, 18));
+  Expect.equals(672749994932560009201, pow(11, 20));
 }
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index dd2b0b7..07c89ac 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -4,6 +4,9 @@
 
 package/invalid_uri_test: Fail, OK # Fails intentionally
 
+[ $runtime == vm && $system == macos ]
+debugger/basic_debugger_test: Pass, Crash # Issue 10488.
+
 [ $runtime == vm ]
 # Fails because checked-in dart executable is not up to date.
 io/test_runner_test: Fail
@@ -16,7 +19,8 @@
 
 [ $runtime == vm ]
 package/package_isolate_test: Fail # http://dartbug.com/7520.
-io/raw_server_socket_cancel_test: Pass, Fail, Timeout # Issue 8675
+# The test is flaky, and is timing out, causing buildbot cycle times to rise.
+io/raw_server_socket_cancel_test: Skip # Issue 8675
 
 [ $runtime == vm && $checked ]
 # These tests have type errors on purpose.
@@ -102,6 +106,7 @@
 package/package_isolate_test: Skip # spawnUri does not work in dart2js. See issue 3051
 debugger/*: Skip # Do not run standalone vm debugger tests with dart2js.
 left_shift_bit_and_op_test: Skip # Integers exceed dart2js precision.
+pow_test: Skip # Precision > 53 bits.
 
 [ $compiler == dart2js && $jscl ]
 assert_test: Fail, OK # Assumes unspecified fields on the AssertionError.
diff --git a/tools/VERSION b/tools/VERSION
index 21722df..402316f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 5
-BUILD 7
-PATCH 3
+BUILD 8
+PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 44163fe..9bccf56 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -119,6 +119,10 @@
 
     user_test = os.environ.get('USER_TEST', 'no')
 
+    # TODO(ricow): temporary hack to run on fyi with --use_browser_controller
+    if os.environ.get('BUILDBOT_SCHEDULER') == "fyi-main" and runtime == 'drt':
+      runtime = 'chrome'
+
     cmd.extend([sys.executable,
                 os.path.join(os.curdir, 'tools', 'test.py'),
                 '--step_name=' + step_name,
@@ -139,6 +143,10 @@
     else:
       cmd.extend(['--progress=buildbot', '-v'])
 
+    # TODO(ricow): temporary hack to run on fyi with --use_browser_controller
+    if os.environ.get('BUILDBOT_SCHEDULER') == "fyi-main":
+      cmd.append('--use_browser_controller')
+
     global IsFirstTestStepCall
     if IsFirstTestStepCall:
       IsFirstTestStepCall = False
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index dae8eca..4a34c77 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -327,6 +327,21 @@
         " */"
       ]
     },
+    "Node": {
+      "members": {
+        "appendChild": [
+          "/**",
+          "   * Adds a node to the end of the child [nodes] list of this node.",
+          "   *",
+          "   * If the node already exists in this document, it will be removed from its",
+          "   * current parent node, then added to this node.",
+          "   *",
+          "   * This method is more efficient than `nodes.add`, and is the preferred",
+          "   * way of appending a child node.",
+          "   */"
+        ]
+      }
+    },
     "WebSocket": {
       "comment": [
         "/**",
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 12e8200..1e9ece5 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -67,7 +67,6 @@
   },
   "AudioBuffer": {
     "comment": "https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioBuffer-section",
-    "dart_action": "default",
     "members": {
       "duration": {},
       "gain": {},
@@ -274,7 +273,6 @@
   },
   "CSSCharsetRule": {
     "comment": "http://dev.w3.org/csswg/cssom/#the-csscharsetrule-interface",
-    "dart_action": "default",
     "members": {
       "encoding": {}
     },
@@ -428,7 +426,6 @@
   "CSSStyleDeclaration": {
     "comment": "http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface",
     "members": {
-      "_getPropertyValue": {},
       "cssText": {},
       "getPropertyCSSValue": {
         "comment": "http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface",
@@ -440,9 +437,7 @@
         "comment": "http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface",
         "support_level": "nonstandard"
       },
-      "getPropertyValue": {
-        "support_level": "untriaged"
-      },
+      "getPropertyValue": {},
       "isPropertyImplicit": {
         "comment": "http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface",
         "support_level": "nonstandard"
@@ -984,10 +979,6 @@
     },
     "support_level": "stable"
   },
-  "DOMException": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "DOMFileSystem": {
     "comment": "http://www.w3.org/TR/file-system-api/",
     "members": {
@@ -1407,7 +1398,7 @@
         "support_level": "untriaged"
       },
       "onwebkitTransitionEnd": {
-        "support_level": "untriaged"
+        "support_level": "deprecated"
       },
       "onwebkitanimationend": {
         "support_level": "experimental"
@@ -1419,7 +1410,7 @@
         "support_level": "experimental"
       },
       "onwebkittransitionend": {
-        "support_level": "experimental"
+        "support_level": "deprecated"
       },
       "open": {},
       "openDatabase": {
@@ -2102,6 +2093,7 @@
     "support_level": "experimental"
   },
   "Element": {
+    "comment": "http://dom.spec.whatwg.org/#interface-element",
     "members": {
       "ALLOW_KEYBOARD_INPUT": {
         "comment": "https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#dom-element-requestfullscreen",
@@ -2112,30 +2104,40 @@
       "blur": {},
       "childElementCount": {},
       "children": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "classList": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#dom-classlist"
       },
       "className": {},
       "click": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "clientHeight": {},
       "clientLeft": {},
       "clientTop": {},
       "clientWidth": {},
       "contentEditable": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "dataset": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#dom-dataset"
       },
       "dir": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "draggable": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "firstElementChild": {},
       "focus": {},
@@ -2162,19 +2164,29 @@
       "hasAttributeNS": {},
       "hasAttributes": {},
       "hidden": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "id": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "innerHTML": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "isContentEditable": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "lang": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "lastElementChild": {},
       "nextElementSibling": {},
@@ -2242,10 +2254,12 @@
         "support_level": "experimental"
       },
       "ontouchenter": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/touch-events/",
+        "support_level": "experimental"
       },
       "ontouchleave": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/touch-events/",
+        "support_level": "experimental"
       },
       "ontouchmove": {
         "comment": "http://www.w3.org/TR/touch-events/",
@@ -2256,7 +2270,7 @@
         "support_level": "experimental"
       },
       "onwebkitTransitionEnd": {
-        "support_level": "untriaged"
+        "support_level": "deprecated"
       },
       "onwebkitfullscreenchange": {
         "comment": "https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html",
@@ -2267,7 +2281,9 @@
         "support_level": "experimental"
       },
       "outerHTML": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "previousElementSibling": {},
       "querySelector": {},
@@ -2305,18 +2321,25 @@
       },
       "setAttributeNodeNS": {},
       "spellcheck": {
-        "support_level": "untriaged"
+        "comment": "http://blog.whatwg.org/the-road-to-html-5-spellchecking",
+        "dart_action": "experimental",
+        "support_level": "nonstandard"
       },
       "style": {},
       "tabIndex": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "tagName": {},
       "title": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
+        "dart_action": "stable",
+        "support_level": "nonstandard"
       },
       "translate": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-translate-attribute",
+        "support_level": "experimental"
       },
       "webkitCreateShadowRoot": {
         "comment": "https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#api-shadow-aware-create-shadow-root",
@@ -2360,7 +2383,8 @@
         "support_level": "experimental"
       },
       "webkitdropzone": {
-        "support_level": "untriaged"
+        "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-dropzone-attribute",
+        "support_level": "experimental"
       }
     },
     "support_level": "stable"
@@ -2931,7 +2955,6 @@
   },
   "HTMLAnchorElement": {
     "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element",
-    "dart_action": "unstable",
     "members": {
       "HTMLAnchorElement": {},
       "charset": {
@@ -3350,7 +3373,11 @@
         "dart_action": "suppress",
         "support_level": "nonstandard"
       },
-      "spellcheck": {},
+      "spellcheck": {
+        "comment": "http://blog.whatwg.org/the-road-to-html-5-spellchecking",
+        "dart_action": "experimental",
+        "support_level": "nonstandard"
+      },
       "tabIndex": {},
       "title": {},
       "translate": {},
@@ -3708,7 +3735,8 @@
       "multiple": {},
       "name": {},
       "onwebkitSpeechChange": {
-        "support_level": "untriaged"
+        "comment": "http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#extending_html_elements",
+        "support_level": "experimental"
       },
       "onwebkitspeechchange": {
         "comment": "http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#extending_html_elements",
@@ -4838,9 +4866,7 @@
     "dart_action": "unstable",
     "members": {
       "advance": {},
-      "continue": {
-        "support_level": "untriaged"
-      },
+      "continue": {},
       "delete": {},
       "direction": {},
       "key": {},
@@ -4915,30 +4941,22 @@
     "comment": "http://www.w3.org/TR/IndexedDB/#idl-def-IDBKeyRange",
     "dart_action": "unstable",
     "members": {
-      "bound": {
-        "support_level": "untriaged"
-      },
+      "bound": {},
       "bound_": {
         "support_level": "nonstandard"
       },
       "lower": {},
-      "lowerBound": {
-        "support_level": "untriaged"
-      },
+      "lowerBound": {},
       "lowerBound_": {
         "support_level": "nonstandard"
       },
       "lowerOpen": {},
-      "only": {
-        "support_level": "untriaged"
-      },
+      "only": {},
       "only_": {
         "support_level": "nonstandard"
       },
       "upper": {},
-      "upperBound": {
-        "support_level": "untriaged"
-      },
+      "upperBound": {},
       "upperBound_": {
         "support_level": "nonstandard"
       },
@@ -5337,12 +5355,8 @@
   "MediaStreamTrack": {
     "comment": "http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack",
     "members": {
-      "addEventListener": {
-        "dart_action": "default"
-      },
-      "dispatchEvent": {
-        "dart_action": "default"
-      },
+      "addEventListener": {},
+      "dispatchEvent": {},
       "enabled": {},
       "id": {},
       "kind": {},
@@ -5430,14 +5444,6 @@
     },
     "support_level": "experimental"
   },
-  "MimeType": {
-    "members": {},
-    "support_level": "untriaged"
-  },
-  "MimeTypeArray": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "MouseEvent": {
     "comment": "http://www.w3.org/TR/DOM-Level-3-Events/#events-mouseevents",
     "members": {
@@ -5514,13 +5520,10 @@
   },
   "MutationObserver": {
     "comment": "http://www.w3.org/TR/domcore/#interface-mutationobserver",
-    "dart_action": "default",
     "members": {
       "_observe": {},
       "disconnect": {},
-      "observe": {
-        "support_level": "untriaged"
-      },
+      "observe": {},
       "takeRecords": {}
     },
     "support_level": "stable"
@@ -5574,7 +5577,6 @@
     "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#navigator",
     "members": {
       "appCodeName": {
-        "dart_action": "default",
         "support_level": "nonstandard"
       },
       "appName": {
@@ -5703,9 +5705,7 @@
     "comment": "http://dom.spec.whatwg.org/#interface-node",
     "members": {
       "ATTRIBUTE_NODE": {},
-      "CDATA_SECTION_NODE": {
-        "dart_action": "default"
-      },
+      "CDATA_SECTION_NODE": {},
       "COMMENT_NODE": {},
       "DOCUMENT_FRAGMENT_NODE": {},
       "DOCUMENT_NODE": {},
@@ -5724,9 +5724,7 @@
       "TEXT_NODE": {},
       "addEventListener": {},
       "appendChild": {},
-      "baseURI": {
-        "dart_action": "default"
-      },
+      "baseURI": {},
       "childNodes": {},
       "cloneNode": {},
       "compareDocumentPosition": {},
@@ -6090,10 +6088,6 @@
     },
     "support_level": "experimental"
   },
-  "Path": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "Performance": {
     "comment": "http://www.w3.org/TR/navigation-timing/#performance",
     "members": {
@@ -6245,14 +6239,6 @@
     },
     "support_level": "stable"
   },
-  "Plugin": {
-    "members": {},
-    "support_level": "untriaged"
-  },
-  "PluginArray": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "PopStateEvent": {
     "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#popstateevent",
     "members": {
@@ -6701,50 +6687,50 @@
     "members": {
       "SVGAElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "target": {},
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -6763,7 +6749,7 @@
       "format": {},
       "glyphRef": {},
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       }
     },
     "support_level": "stable"
@@ -6936,34 +6922,34 @@
     "members": {
       "SVGAnimationElement": {},
       "beginElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/animate.html#InterfaceElementTimeControl"
       },
       "beginElementAt": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/animate.html#InterfaceElementTimeControl"
       },
       "endElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/animate.html#InterfaceElementTimeControl"
       },
       "endElementAt": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/animate.html#InterfaceElementTimeControl"
       },
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "getCurrentTime": {},
       "getSimpleDuration": {},
       "getStartTime": {},
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "targetElement": {}
     },
@@ -6977,47 +6963,47 @@
       "cx": {},
       "cy": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "r": {},
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -7029,46 +7015,46 @@
       "SVGClipPathElement": {},
       "clipPathUnits": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -7125,46 +7111,46 @@
     "members": {
       "SVGDefsElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -7175,10 +7161,10 @@
     "members": {
       "SVGDescElement": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -7278,48 +7264,48 @@
       "cx": {},
       "cy": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "rx": {},
       "ry": {},
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -7364,22 +7350,22 @@
       "SVG_FEBLEND_MODE_SCREEN": {},
       "SVG_FEBLEND_MODE_UNKNOWN": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "in2": {},
       "mode": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7395,22 +7381,22 @@
       "SVG_FECOLORMATRIX_TYPE_SATURATE": {},
       "SVG_FECOLORMATRIX_TYPE_UNKNOWN": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "type": {},
       "values": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7421,20 +7407,20 @@
     "members": {
       "SVGFEComponentTransferElement": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7451,7 +7437,7 @@
       "SVG_FECOMPOSITE_OPERATOR_UNKNOWN": {},
       "SVG_FECOMPOSITE_OPERATOR_XOR": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "in2": {},
@@ -7461,16 +7447,16 @@
       "k4": {},
       "operator": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7488,7 +7474,7 @@
       "divisor": {},
       "edgeMode": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "kernelMatrix": {},
@@ -7498,18 +7484,18 @@
       "orderY": {},
       "preserveAlpha": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "targetX": {},
       "targetY": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7521,23 +7507,23 @@
       "SVGFEDiffuseLightingElement": {},
       "diffuseConstant": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "kernelUnitLengthX": {},
       "kernelUnitLengthY": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "surfaceScale": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7553,23 +7539,23 @@
       "SVG_CHANNEL_R": {},
       "SVG_CHANNEL_UNKNOWN": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "in2": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "scale": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "xChannelSelector": {},
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "yChannelSelector": {}
     },
@@ -7603,19 +7589,19 @@
     "members": {
       "SVGFEFloodElement": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7658,23 +7644,23 @@
     "members": {
       "SVGFEGaussianBlurElement": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "setStdDeviation": {},
       "stdDeviationX": {},
       "stdDeviationY": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7685,32 +7671,32 @@
     "members": {
       "SVGFEImageElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "preserveAspectRatio": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7721,19 +7707,19 @@
     "members": {
       "SVGFEMergeElement": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7755,24 +7741,24 @@
       "SVG_MORPHOLOGY_OPERATOR_ERODE": {},
       "SVG_MORPHOLOGY_OPERATOR_UNKNOWN": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "operator": {},
       "radiusX": {},
       "radiusY": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "setRadius": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7785,20 +7771,20 @@
       "dx": {},
       "dy": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7820,23 +7806,23 @@
     "members": {
       "SVGFESpecularLightingElement": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "specularConstant": {},
       "specularExponent": {},
       "surfaceScale": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7863,20 +7849,20 @@
     "members": {
       "SVGFETileElement": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "in1": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7895,23 +7881,23 @@
       "baseFrequencyX": {},
       "baseFrequencyY": {},
       "height": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "numOctaves": {},
       "result": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "seed": {},
       "stitchTiles": {},
       "type": {},
       "width": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "x": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       },
       "y": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/filters.html#InterfaceSVGFilterPrimitiveStandardAttributes"
       }
     },
     "support_level": "stable"
@@ -7922,24 +7908,24 @@
     "members": {
       "SVGFilterElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "filterResX": {},
       "filterResY": {},
       "filterUnits": {},
       "height": {},
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "primitiveUnits": {},
       "setFilterRes": {},
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {}
     },
@@ -8008,49 +7994,49 @@
     "members": {
       "SVGForeignObjectElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "height": {},
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {}
     },
@@ -8062,46 +8048,46 @@
     "members": {
       "SVGGElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -8136,12 +8122,12 @@
       "SVG_SPREADMETHOD_REPEAT": {},
       "SVG_SPREADMETHOD_UNKNOWN": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "gradientTransform": {},
       "gradientUnits": {},
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "spreadMethod": {}
     },
@@ -8161,53 +8147,53 @@
     "members": {
       "SVGImageElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "height": {},
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "preserveAspectRatio": {},
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {}
     },
@@ -8267,48 +8253,48 @@
     "members": {
       "SVGLineElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "x1": {},
       "x2": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y1": {},
       "y2": {}
@@ -8359,7 +8345,7 @@
       "SVG_MARKER_ORIENT_AUTO": {},
       "SVG_MARKER_ORIENT_UNKNOWN": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "markerHeight": {},
       "markerUnits": {},
@@ -8367,20 +8353,20 @@
       "orientAngle": {},
       "orientType": {},
       "preserveAspectRatio": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "refX": {},
       "refY": {},
       "setOrientToAngle": {},
       "setOrientToAuto": {},
       "viewBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -8391,30 +8377,30 @@
     "members": {
       "SVGMaskElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "height": {},
       "maskContentUnits": {},
       "maskUnits": {},
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {}
     },
@@ -8527,52 +8513,52 @@
       "createSVGPathSegMovetoAbs": {},
       "createSVGPathSegMovetoRel": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getPathSegAtLength": {},
       "getPointAtLength": {},
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTotalLength": {},
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "normalizedPathSegList": {},
       "pathLength": {},
       "pathSegList": {},
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -8817,40 +8803,40 @@
     "members": {
       "SVGPatternElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "height": {},
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "patternContentUnits": {},
       "patternTransform": {},
       "patternUnits": {},
       "preserveAspectRatio": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "viewBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {}
     },
@@ -8888,47 +8874,47 @@
       "SVGPolygonElement": {},
       "animatedPoints": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "points": {},
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -8940,47 +8926,47 @@
       "SVGPolylineElement": {},
       "animatedPoints": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "points": {},
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -9039,51 +9025,51 @@
     "members": {
       "SVGRectElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "height": {},
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "rx": {},
       "ry": {},
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {}
     },
@@ -9124,76 +9110,76 @@
       "currentView": {},
       "deselectAll": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "forceRedraw": {},
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCurrentTime": {},
       "getElementById": {},
       "getEnclosureList": {},
       "getIntersectionList": {},
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "height": {},
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "pauseAnimations": {},
       "pixelUnitToMillimeterX": {},
       "pixelUnitToMillimeterY": {},
       "preserveAspectRatio": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "screenPixelToMillimeterX": {},
       "screenPixelToMillimeterY": {},
       "setCurrentTime": {},
       "suspendRedraw": {},
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "unpauseAnimations": {},
       "unsuspendRedraw": {},
       "unsuspendRedrawAll": {},
       "useCurrentView": {},
       "viewBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "viewport": {},
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {},
       "zoomAndPan": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGZoomAndPan"
       }
     },
     "support_level": "stable"
@@ -9204,10 +9190,10 @@
     "members": {
       "SVGScriptElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "type": {}
     },
@@ -9255,10 +9241,10 @@
       "title": {},
       "type": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "nonstandard"
@@ -9279,46 +9265,46 @@
     "members": {
       "SVGSwitchElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -9329,19 +9315,19 @@
     "members": {
       "SVGSymbolElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "preserveAspectRatio": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "viewBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -9381,7 +9367,7 @@
       "LENGTHADJUST_SPACINGANDGLYPHS": {},
       "LENGTHADJUST_UNKNOWN": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "getCharNumAtPosition": {},
       "getComputedTextLength": {},
@@ -9392,25 +9378,25 @@
       "getStartPositionOfChar": {},
       "getSubStringLength": {},
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "lengthAdjust": {},
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "selectSubString": {},
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "textLength": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -9421,25 +9407,25 @@
     "members": {
       "SVGTextElement": {},
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       }
     },
     "support_level": "stable"
@@ -9455,7 +9441,7 @@
       "TEXTPATH_SPACINGTYPE_EXACT": {},
       "TEXTPATH_SPACINGTYPE_UNKNOWN": {},
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "method": {},
       "spacing": {},
@@ -9481,10 +9467,10 @@
     "members": {
       "SVGTitleElement": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       }
     },
     "support_level": "stable"
@@ -9534,22 +9520,22 @@
     "dart_action": "unstable",
     "members": {
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "transform": {}
     },
@@ -9580,53 +9566,53 @@
       "SVGUseElement": {},
       "animatedInstanceRoot": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "farthestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getBBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getScreenCTM": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "getTransformToElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "hasExtension": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "height": {},
       "href": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGURIReference"
       },
       "instanceRoot": {},
       "nearestViewportElement": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
       },
       "requiredExtensions": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "requiredFeatures": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "systemLanguage": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTests"
       },
       "transform": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGTransformable"
       },
       "width": {},
       "x": {},
       "xmllang": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "xmlspace": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGLangSpace"
       },
       "y": {}
     },
@@ -9646,17 +9632,17 @@
     "members": {
       "SVGViewElement": {},
       "externalResourcesRequired": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGExternalResourcesRequired"
       },
       "preserveAspectRatio": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "viewBox": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGFitToViewBox"
       },
       "viewTarget": {},
       "zoomAndPan": {
-        "support_level": "untriaged"
+        "comment": "http://www.w3.org/TR/SVG/types.html#InterfaceSVGZoomAndPan"
       }
     },
     "support_level": "stable"
@@ -9764,10 +9750,6 @@
     },
     "support_level": "nonstandard"
   },
-  "SecurityPolicy": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "SecurityPolicyViolationEvent": {
     "comment": "https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#securitypolicyviolationevent-events",
     "members": {
@@ -9782,10 +9764,6 @@
     },
     "support_level": "experimental"
   },
-  "Selection": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "ShadowRoot": {
     "comment": "https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#api-shadow-root",
     "members": {
@@ -10330,10 +10308,6 @@
     },
     "support_level": "stable"
   },
-  "URL": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "Uint16Array": {
     "comment": "http://www.khronos.org/registry/typedarray/specs/latest/",
     "members": {
@@ -11005,15 +10979,6 @@
     "members": {},
     "support_level": "experimental"
   },
-  "WebKitAnimationEvent": {
-    "comment": "http://www.w3.org/TR/css3-animations/#AnimationEvent-interface",
-    "dart_action": "suppress",
-    "members": {
-      "animationName": {},
-      "elapsedTime": {}
-    },
-    "support_level": "deprecated"
-  },
   "WebKitCSSFilterRule": {
     "comment": "http://www.w3.org/TR/filter-effects/",
     "members": {
@@ -11142,45 +11107,6 @@
     },
     "support_level": "deprecated"
   },
-  "WebKitNamedFlow": {
-    "comment": "http://www.w3.org/TR/css3-regions/#dom-named-flow-collection",
-    "dart_action": "suppress",
-    "members": {
-      "addEventListener": {},
-      "dispatchEvent": {},
-      "firstEmptyRegionIndex": {},
-      "getContent": {},
-      "getRegions": {},
-      "getRegionsByContent": {},
-      "name": {},
-      "overset": {},
-      "removeEventListener": {}
-    },
-    "support_level": "experimental"
-  },
-  "WebKitNamedFlowCollection": {
-    "members": {},
-    "support_level": "untriaged"
-  },
-  "WebKitPoint": {
-    "comment": "http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html",
-    "dart_action": "private",
-    "members": {
-      "x": {},
-      "y": {}
-    },
-    "support_level": "nonstandard"
-  },
-  "WebKitTransitionEvent": {
-    "comment": "http://dev.w3.org/csswg/css-transitions/#Events-TransitionEvent",
-    "dart_action": "suppress",
-    "members": {
-      "elapsedTime": {},
-      "propertyName": {},
-      "pseudoElement": {}
-    },
-    "support_level": "deprecated"
-  },
   "WebSocket": {
     "comment": "http://www.w3.org/TR/websockets/#the-websocket-interface",
     "dart_action": "unstable",
@@ -11220,7 +11146,6 @@
       "DOM_DELTA_PIXEL": {},
       "deltaMode": {},
       "initWebKitWheelEvent": {
-        "dart_action": "default",
         "support_level": "experimental"
       },
       "webkitDirectionInvertedFromDevice": {
@@ -11238,10 +11163,6 @@
     },
     "support_level": "stable"
   },
-  "Window": {
-    "members": {},
-    "support_level": "untriaged"
-  },
   "Worker": {
     "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#worker",
     "dart_action": "experimental",
@@ -11334,7 +11255,6 @@
   },
   "WorkerLocation": {
     "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workerlocation",
-    "dart_action": "default",
     "members": {
       "hash": {
         "comment": "http://url.spec.whatwg.org/#urlutils"
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index ce2f9f8..bcbe91b 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -16,7 +16,7 @@
 from generator import ConstantOutputOrder
 from htmlrenamer import renamed_html_members, html_interface_renames
 
-_logger = logging.getLogger('DartMetadata')
+_logger = logging.getLogger('dartmetadata')
 
 # Annotations to be placed on native members.  The table is indexed by the IDL
 # interface and member name, and by IDL return or field type name.  Both are
@@ -383,6 +383,7 @@
   'Worker': _all_but_ie9_annotations,
   'XMLHttpRequest.onloadend': _all_but_ie9_annotations,
   'XMLHttpRequest.onprogress': _all_but_ie9_annotations,
+  'XMLHttpRequest.overrideMimeType': _no_ie_annotations,
   'XMLHttpRequest.response': _all_but_ie9_annotations,
   'XMLHttpRequestProgressEvent': _webkit_experimental_annotations,
   'XSLTProcessor': [
@@ -581,7 +582,7 @@
     elif support_level == 'deprecated':
       return '@Deprecated'
     else:
-      _logger.warn('Unknown support_level - %s:%s' % (interface.id, member_id))
+      _logger.warn('Unknown support_level - %s:%s' % (interface_id, member_id))
 
   def Flush(self):
     json_file = open(self._api_status_path, 'w+')
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index d22b6cd..0dc1054 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -131,8 +131,14 @@
         self._interface.id, constant, constant.id, 'get:', dartify_name=False)
     if not const_name:
       return
+
+    annotations = self._metadata.GetFormattedMetadata(
+        self._library_name, self._interface, constant.id, '  ')
+
     type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id)
-    self._members_emitter.Emit('\n  static const $TYPE$NAME = $VALUE;\n',
+    self._members_emitter.Emit(
+        '\n  $(ANNOTATIONS)static const $TYPE$NAME = $VALUE;\n',
+        ANNOTATIONS=annotations,
         NAME=const_name,
         TYPE=type,
         VALUE=constant.value)
@@ -384,46 +390,23 @@
             CTOR_FACTORY_NAME=factory_constructor_name,
             FACTORY_PARAMS=factory_parameters)
       else:
-        if has_factory_provider:
-          dispatcher_emitter = self._members_emitter.Emit(
-              '\n  $(METADATA)'
-              'factory $CTOR($PARAMS) {\n'
-              '$!DISPATCHER'
-              '    return $FACTORY._create($FACTORY_PARAMS);\n'
-              '  }\n',
-              CTOR=constructor_info._ConstructorFullName(self._DartType),
-              PARAMS=constructor_info.ParametersDeclaration(self._DartType),
-              FACTORY=factory_name,
-              METADATA=metadata,
-              FACTORY_PARAMS=constructor_info.ParametersAsArgumentList())
+        inits = self._members_emitter.Emit(
+            '\n  $(METADATA)'
+            'factory $CONSTRUCTOR($PARAMS) {\n'
+            '    var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n'
+            '$!INITS'
+            '    return e;\n'
+            '  }\n',
+            CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType),
+            METADATA=metadata,
+            FACTORY=factory_name,
+            CTOR_FACTORY_NAME=factory_constructor_name,
+            PARAMS=constructor_info.ParametersDeclaration(self._DartType),
+            FACTORY_PARAMS=factory_parameters)
 
-          for index, param_info in enumerate(constructor_info.param_infos):
-            if param_info.is_optional:
-              dispatcher_emitter.Emit(
-                '    if ($OPT_PARAM_NAME == null) {\n'
-                '      return $FACTORY._create($FACTORY_PARAMS);\n'
-                '    }\n',
-                OPT_PARAM_NAME=param_info.name,
-                FACTORY=factory_name,
-                FACTORY_PARAMS=constructor_info.ParametersAsArgumentList(index))
-        else:
-          inits = self._members_emitter.Emit(
-              '\n  $(METADATA)'
-              'factory $CONSTRUCTOR($PARAMS) {\n'
-              '    var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n'
-              '$!INITS'
-              '    return e;\n'
-              '  }\n',
-              CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType),
-              METADATA=metadata,
-              FACTORY=factory_name,
-              CTOR_FACTORY_NAME=factory_constructor_name,
-              PARAMS=constructor_info.ParametersDeclaration(self._DartType),
-              FACTORY_PARAMS=factory_parameters)
-
-          for index, param_info in enumerate(constructor_info.param_infos):
-            if param_info.is_optional:
-              inits.Emit('    if ($E != null) e.$E = $E;\n', E=param_info.name)
+        for index, param_info in enumerate(constructor_info.param_infos):
+          if param_info.is_optional:
+            inits.Emit('    if ($E != null) e.$E = $E;\n', E=param_info.name)
     else:
       def GenerateCall(
           stmts_emitter, call_emitter,
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 25e66d6..2a512c9 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -311,6 +311,7 @@
 # identical functionality but with cleaner names.
 renamed_html_members = monitored.Dict('htmlrenamer.renamed_html_members', {
     'CSSStyleDeclaration.getPropertyValue': '_getPropertyValue',
+    'CSSStyleDeclaration.setProperty': '_setProperty',
     'DirectoryEntry.getDirectory': '_getDirectory',
     'DirectoryEntry.getFile': '_getFile',
     'Document.createCDATASection': 'createCDataSection',
diff --git a/tools/dom/scripts/logging.conf b/tools/dom/scripts/logging.conf
index b9d3e98..8645a8e 100644
--- a/tools/dom/scripts/logging.conf
+++ b/tools/dom/scripts/logging.conf
@@ -1,5 +1,5 @@
 [loggers]
-keys=root,pegparser,database,databasebuilder,dartgenerator,snippet_manager,htmlrenamer
+keys=root,pegparser,database,databasebuilder,dartgenerator,dartmetadata,snippet_manager,htmlrenamer
 
 [handlers]
 keys=consoleHandler
@@ -53,6 +53,12 @@
 handlers=consoleHandler
 qualname=htmlrenamer
 
+[logger_dartmetadata]
+level=INFO
+propagate=0
+handlers=consoleHandler
+qualname=dartmetadata
+
 [formatter_simpleFormatter]
 format=%(name)s - %(levelname)s - %(message)s
 datefmt=
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 6adefad..0302a6c 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -528,7 +528,7 @@
     if mixins:
       mixins_str = ' with ' + ', '.join(mixins)
       if not base_class:
-        base_class = 'Object'
+        base_class = 'Interceptor'
 
     annotations = self._metadata.GetFormattedMetadata(
         self._library_name, self._interface, None, '')
@@ -712,19 +712,22 @@
       'CustomIndexedSetter' in ext_attrs)
 
     if has_indexed_getter:
+      indexed_getter = ('JS("%s", "#[#]", this, index)' %
+          self.SecureOutputType(element_type));
+    elif any(op.id == 'getItem' for op in self._interface.operations):
+      indexed_getter = 'this.getItem(index)'
+    elif any(op.id == 'item' for op in self._interface.operations):
+      indexed_getter = 'this.item(index)'
+
+    if indexed_getter:
       self._members_emitter.Emit(
           '\n'
-          '  $TYPE operator[](int index) => '
-          'JS("$TYPE", "#[#]", this, index);\n',
-          TYPE=self.SecureOutputType(element_type))
-    else:
-      if any(op.id == 'getItem' for op in self._interface.operations):
-        indexed_getter = 'this.getItem(index)'
-      elif any(op.id == 'item' for op in self._interface.operations):
-        indexed_getter = 'this.item(index)'
-      self._members_emitter.Emit(
-          '\n'
-          '  $TYPE operator[](int index) => $INDEXED_GETTER;\n',
+          '  $TYPE operator[](int index) {\n'
+          '    if (JS("bool", "# >>> 0 !== # || # >= #", index,\n'
+          '        index, index, length))\n'
+          '      throw new RangeError.range(index, 0, length);\n'
+          '    return $INDEXED_GETTER;\n'
+          '  }',
           INDEXED_GETTER=indexed_getter,
           TYPE=self.SecureOutputType(element_type))
 
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 4c61854..2c955bd 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -428,7 +428,12 @@
     else:
       self._members_emitter.Emit(
           '\n'
-          '  $TYPE operator[](int index) native "$(INTERFACE)_item_Callback";\n',
+          '  $TYPE operator[](int index) {\n'
+          '    if (index < 0 || index >= length)\n'
+          '      throw new RangeError.range(index, 0, length);\n'
+          '    return _nativeIndexedGetter(index);\n'
+          '  }\n'
+          '  $TYPE _nativeIndexedGetter(int index) native "$(INTERFACE)_item_Callback";\n',
           TYPE=self.SecureOutputType(element_type),
           INTERFACE=self._interface.id)
 
diff --git a/tools/dom/src/TemplateBindings.dart b/tools/dom/src/TemplateBindings.dart
index 5192927..9841aee 100644
--- a/tools/dom/src/TemplateBindings.dart
+++ b/tools/dom/src/TemplateBindings.dart
@@ -5,7 +5,7 @@
 part of html;
 
 // This code is a port of Model-Driven-Views:
-// https://github.com/toolkitchen/mdv
+// https://github.com/polymer-project/mdv
 // The code mostly comes from src/template_element.js
 
 typedef void _ChangeHandler(value);
@@ -37,7 +37,7 @@
  *
  *     TemplateElement.syntax['MySyntax'] = new MySyntax();
  *
- * See <https://github.com/toolkitchen/mdv/blob/master/docs/syntax.md> for more
+ * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for more
  * information about Custom Syntax.
  */
 // TODO(jmesserly): if this is just one method, a function type would make it
@@ -246,19 +246,6 @@
   }
 }
 
-Stream<Event> _getStreamForInputType(InputElement element) {
-  switch (element.type) {
-    case 'checkbox':
-      return element.onClick;
-    case 'radio':
-    case 'select-multiple':
-    case 'select-one':
-      return element.onChange;
-    default:
-      return element.onInput;
-  }
-}
-
 abstract class _InputBinding {
   final InputElement element;
   PathObserver binding;
@@ -280,6 +267,20 @@
     _pathSub.cancel();
     _eventSub.cancel();
   }
+
+
+  static Stream<Event> _getStreamForInputType(InputElement element) {
+    switch (element.type) {
+      case 'checkbox':
+        return element.onClick;
+      case 'radio':
+      case 'select-multiple':
+      case 'select-one':
+        return element.onChange;
+      default:
+        return element.onInput;
+    }
+  }
 }
 
 class _ValueBinding extends _InputBinding {
@@ -294,18 +295,11 @@
   }
 }
 
-// TODO(jmesserly): not sure what kind of boolean conversion rules to
-// apply for template data-binding. HTML attributes are true if they're present.
-// However Dart only treats "true" as true. Since this is HTML we'll use
-// something closer to the HTML rules: null (missing) and false are false,
-// everything else is true. See: https://github.com/toolkitchen/mdv/issues/59
-bool _templateBooleanConversion(value) => null != value && false != value;
-
 class _CheckedBinding extends _InputBinding {
   _CheckedBinding(element, model, path) : super(element, model, path);
 
   void valueChanged(value) {
-    element.checked = _templateBooleanConversion(value);
+    element.checked = _Bindings._toBoolean(value);
   }
 
   void updateBinding(e) {
@@ -324,220 +318,309 @@
       }
     }
   }
-}
 
-// TODO(jmesserly): polyfill document.contains API instead of doing it here
-bool _isNodeInDocument(Node node) {
-  // On non-IE this works:
-  // return node.document.contains(node);
-  var document = node.document;
-  if (node == document || node.parentNode == document) return true;
-  return document.documentElement.contains(node);
-}
-
-// |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
-// Returns an array containing all radio buttons other than |element| that
-// have the same |name|, either in the form that |element| belongs to or,
-// if no form, in the document tree to which |element| belongs.
-//
-// This implementation is based upon the HTML spec definition of a
-// "radio button group":
-//   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
-//
-Iterable _getAssociatedRadioButtons(element) {
-  if (!_isNodeInDocument(element)) return [];
-  if (element.form != null) {
-    return element.form.nodes.where((el) {
-      return el != element &&
-          el is InputElement &&
-          el.type == 'radio' &&
-          el.name == element.name;
-    });
-  } else {
-    var radios = element.document.queryAll(
-        'input[type="radio"][name="${element.name}"]');
-    return radios.where((el) => el != element && el.form == null);
-  }
-}
-
-Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
-  var clone = node.clone(false); // Shallow clone.
-  if (clone is Element && clone.isTemplate) {
-    TemplateElement.decorate(clone, node);
-    if (syntax != null) {
-      clone.attributes.putIfAbsent('syntax', () => syntax);
-    }
-  }
-
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
-  }
-  return clone;
-}
-
-// http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-Document _getTemplateContentsOwner(Document doc) {
-  if (doc.window == null) {
-    return doc;
-  }
-  var d = doc._templateContentsOwner;
-  if (d == null) {
-    // TODO(arv): This should either be a Document or HTMLDocument depending
-    // on doc.
-    d = doc.implementation.createHtmlDocument('');
-    while (d.$dom_lastChild != null) {
-      d.$dom_lastChild.remove();
-    }
-    doc._templateContentsOwner = d;
-  }
-  return d;
-}
-
-Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
-  var clone = templateElement.clone(false);
-  var attributes = templateElement.attributes;
-  for (var name in attributes.keys.toList()) {
-    switch (name) {
-      case 'template':
-      case 'repeat':
-      case 'bind':
-      case 'ref':
-        clone.attributes.remove(name);
-        break;
-      default:
-        attributes.remove(name);
-        break;
-    }
-  }
-
-  return clone;
-}
-
-void _liftNonNativeTemplateChildrenIntoContent(Element templateElement) {
-  var content = templateElement.content;
-
-  if (!templateElement._isAttributeTemplate) {
-    var child;
-    while ((child = templateElement.$dom_firstChild) != null) {
-      content.append(child);
-    }
-    return;
-  }
-
-  // For attribute templates we copy the whole thing into the content and
-  // we move the non template attributes into the content.
+  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
+  // Returns an array containing all radio buttons other than |element| that
+  // have the same |name|, either in the form that |element| belongs to or,
+  // if no form, in the document tree to which |element| belongs.
   //
-  //   <tr foo template>
+  // This implementation is based upon the HTML spec definition of a
+  // "radio button group":
+  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
   //
-  // becomes
-  //
-  //   <tr template>
-  //   + #document-fragment
-  //     + <tr foo>
-  //
-  var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
-  var child;
-  while ((child = templateElement.$dom_firstChild) != null) {
-    newRoot.append(child);
-  }
-  content.append(newRoot);
-}
-
-void _bootstrapTemplatesRecursivelyFrom(Node node) {
-  void bootstrap(template) {
-    if (!TemplateElement.decorate(template)) {
-      _bootstrapTemplatesRecursivelyFrom(template.content);
+  static Iterable _getAssociatedRadioButtons(element) {
+    if (!_isNodeInDocument(element)) return [];
+    if (element.form != null) {
+      return element.form.nodes.where((el) {
+        return el != element &&
+            el is InputElement &&
+            el.type == 'radio' &&
+            el.name == element.name;
+      });
+    } else {
+      var radios = element.document.queryAll(
+          'input[type="radio"][name="${element.name}"]');
+      return radios.where((el) => el != element && el.form == null);
     }
   }
 
-  // Need to do this first as the contents may get lifted if |node| is
-  // template.
-  // TODO(jmesserly): node is DocumentFragment or Element
-  var templateDescendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-  if (node is Element && node.isTemplate) bootstrap(node);
-
-  templateDescendents.forEach(bootstrap);
-}
-
-final String _allTemplatesSelectors = 'template, option[template], ' +
-    Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
-  if (node is Element) {
-    _addAttributeBindings(node, model, syntax);
-  } else if (node is Text) {
-    _parseAndBind(node, 'text', node.text, model, syntax);
-  }
-
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    _addBindings(c, model, syntax);
+  // TODO(jmesserly): polyfill document.contains API instead of doing it here
+  static bool _isNodeInDocument(Node node) {
+    // On non-IE this works:
+    // return node.document.contains(node);
+    var document = node.document;
+    if (node == document || node.parentNode == document) return true;
+    return document.documentElement.contains(node);
   }
 }
 
+class _Bindings {
+  // TODO(jmesserly): not sure what kind of boolean conversion rules to
+  // apply for template data-binding. HTML attributes are true if they're
+  // present. However Dart only treats "true" as true. Since this is HTML we'll
+  // use something closer to the HTML rules: null (missing) and false are false,
+  // everything else is true. See: https://github.com/polymer-project/mdv/issues/59
+  static bool _toBoolean(value) => null != value && false != value;
 
-void _addAttributeBindings(Element element, model, syntax) {
-  element.attributes.forEach((name, value) {
-    if (value == '' && (name == 'bind' || name == 'repeat')) {
-      value = '{{}}';
-    }
-    _parseAndBind(element, name, value, model, syntax);
-  });
-}
-
-void _parseAndBind(Node node, String name, String text, model,
-    CustomBindingSyntax syntax) {
-
-  var tokens = _parseMustacheTokens(text);
-  if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
-    return;
-  }
-
-  if (tokens.length == 1 && tokens[0].isBinding) {
-    _bindOrDelegate(node, name, model, tokens[0].value, syntax);
-    return;
-  }
-
-  var replacementBinding = new CompoundBinding();
-  for (var i = 0; i < tokens.length; i++) {
-    var token = tokens[i];
-    if (token.isBinding) {
-      _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
-    }
-  }
-
-  replacementBinding.combinator = (values) {
-    var newValue = new StringBuffer();
-
-    for (var i = 0; i < tokens.length; i++) {
-      var token = tokens[i];
-      if (token.isText) {
-        newValue.write(token.value);
-      } else {
-        var value = values[i];
-        if (value != null) {
-          newValue.write(value);
-        }
+  static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
+    var clone = node.clone(false); // Shallow clone.
+    if (clone is Element && clone.isTemplate) {
+      TemplateElement.decorate(clone, node);
+      if (syntax != null) {
+        clone.attributes.putIfAbsent('syntax', () => syntax);
       }
     }
 
-    return newValue.toString();
-  };
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
+    }
+    return clone;
+  }
 
-  node.bind(name, replacementBinding, 'value');
-}
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  static Document _getTemplateContentsOwner(Document doc) {
+    if (doc.window == null) {
+      return doc;
+    }
+    var d = doc._templateContentsOwner;
+    if (d == null) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHtmlDocument('');
+      while (d.$dom_lastChild != null) {
+        d.$dom_lastChild.remove();
+      }
+      doc._templateContentsOwner = d;
+    }
+    return d;
+  }
 
-void _bindOrDelegate(node, name, model, String path,
-    CustomBindingSyntax syntax) {
+  static Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
+    var clone = templateElement.clone(false);
+    var attributes = templateElement.attributes;
+    for (var name in attributes.keys.toList()) {
+      switch (name) {
+        case 'template':
+        case 'repeat':
+        case 'bind':
+        case 'ref':
+          clone.attributes.remove(name);
+          break;
+        default:
+          attributes.remove(name);
+          break;
+      }
+    }
 
-  if (syntax != null) {
-    var delegateBinding = syntax.getBinding(model, path, name, node);
-    if (delegateBinding != null) {
-      model = delegateBinding;
-      path = 'value';
+    return clone;
+  }
+
+  static void _liftNonNativeChildrenIntoContent(Element templateElement) {
+    var content = templateElement.content;
+
+    if (!templateElement._isAttributeTemplate) {
+      var child;
+      while ((child = templateElement.$dom_firstChild) != null) {
+        content.append(child);
+      }
+      return;
+    }
+
+    // For attribute templates we copy the whole thing into the content and
+    // we move the non template attributes into the content.
+    //
+    //   <tr foo template>
+    //
+    // becomes
+    //
+    //   <tr template>
+    //   + #document-fragment
+    //     + <tr foo>
+    //
+    var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
+    var child;
+    while ((child = templateElement.$dom_firstChild) != null) {
+      newRoot.append(child);
+    }
+    content.append(newRoot);
+  }
+
+  static void _bootstrapTemplatesRecursivelyFrom(Node node) {
+    void bootstrap(template) {
+      if (!TemplateElement.decorate(template)) {
+        _bootstrapTemplatesRecursivelyFrom(template.content);
+      }
+    }
+
+    // Need to do this first as the contents may get lifted if |node| is
+    // template.
+    // TODO(jmesserly): node is DocumentFragment or Element
+    var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
+    if (node is Element && node.isTemplate) bootstrap(node);
+
+    descendents.forEach(bootstrap);
+  }
+
+  static final String _allTemplatesSelectors = 'template, option[template], ' +
+      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
+
+  static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
+    if (node is Element) {
+      _addAttributeBindings(node, model, syntax);
+    } else if (node is Text) {
+      _parseAndBind(node, 'text', node.text, model, syntax);
+    }
+
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      _addBindings(c, model, syntax);
     }
   }
 
-  node.bind(name, model, path);
+  static void _addAttributeBindings(Element element, model, syntax) {
+    element.attributes.forEach((name, value) {
+      if (value == '' && (name == 'bind' || name == 'repeat')) {
+        value = '{{}}';
+      }
+      _parseAndBind(element, name, value, model, syntax);
+    });
+  }
+
+  static void _parseAndBind(Node node, String name, String text, model,
+      CustomBindingSyntax syntax) {
+
+    var tokens = _parseMustacheTokens(text);
+    if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
+      return;
+    }
+
+    // If this is a custom element, give the .xtag a change to bind.
+    node = _nodeOrCustom(node);
+
+    if (tokens.length == 1 && tokens[0].isBinding) {
+      _bindOrDelegate(node, name, model, tokens[0].value, syntax);
+      return;
+    }
+
+    var replacementBinding = new CompoundBinding();
+    for (var i = 0; i < tokens.length; i++) {
+      var token = tokens[i];
+      if (token.isBinding) {
+        _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
+      }
+    }
+
+    replacementBinding.combinator = (values) {
+      var newValue = new StringBuffer();
+
+      for (var i = 0; i < tokens.length; i++) {
+        var token = tokens[i];
+        if (token.isText) {
+          newValue.write(token.value);
+        } else {
+          var value = values[i];
+          if (value != null) {
+            newValue.write(value);
+          }
+        }
+      }
+
+      return newValue.toString();
+    };
+
+    node.bind(name, replacementBinding, 'value');
+  }
+
+  static void _bindOrDelegate(node, name, model, String path,
+      CustomBindingSyntax syntax) {
+
+    if (syntax != null) {
+      var delegateBinding = syntax.getBinding(model, path, name, node);
+      if (delegateBinding != null) {
+        model = delegateBinding;
+        path = 'value';
+      }
+    }
+
+    node.bind(name, model, path);
+  }
+
+  /**
+   * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
+   * the node. This is used so nodes can override [Node.bind], [Node.unbind],
+   * and [Node.unbindAll] like InputElement does.
+   */
+  // TODO(jmesserly): remove this when we can extend Element for real.
+  static _nodeOrCustom(node) => node is Element ? node.xtag : node;
+
+  static List<_BindingToken> _parseMustacheTokens(String s) {
+    var result = [];
+    var length = s.length;
+    var index = 0, lastIndex = 0;
+    while (lastIndex < length) {
+      index = s.indexOf('{{', lastIndex);
+      if (index < 0) {
+        result.add(new _BindingToken(s.substring(lastIndex)));
+        break;
+      } else {
+        // There is a non-empty text run before the next path token.
+        if (index > 0 && lastIndex < index) {
+          result.add(new _BindingToken(s.substring(lastIndex, index)));
+        }
+        lastIndex = index + 2;
+        index = s.indexOf('}}', lastIndex);
+        if (index < 0) {
+          var text = s.substring(lastIndex - 2);
+          if (result.length > 0 && result.last.isText) {
+            result.last.value += text;
+          } else {
+            result.add(new _BindingToken(text));
+          }
+          break;
+        }
+
+        var value = s.substring(lastIndex, index).trim();
+        result.add(new _BindingToken(value, isBinding: true));
+        lastIndex = index + 2;
+      }
+    }
+    return result;
+  }
+
+  static void _addTemplateInstanceRecord(fragment, model) {
+    if (fragment.$dom_firstChild == null) {
+      return;
+    }
+
+    var instanceRecord = new TemplateInstance(
+        fragment.$dom_firstChild, fragment.$dom_lastChild, model);
+
+    var node = instanceRecord.firstNode;
+    while (node != null) {
+      node._templateInstance = instanceRecord;
+      node = node.nextNode;
+    }
+  }
+
+  static void _removeAllBindingsRecursively(Node node) {
+    _nodeOrCustom(node).unbindAll();
+    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
+      _removeAllBindingsRecursively(c);
+    }
+  }
+
+  static void _removeChild(Node parent, Node child) {
+    child._templateInstance = null;
+    if (child is Element && child.isTemplate) {
+      // Make sure we stop observing when we remove an element.
+      var templateIterator = child._templateIterator;
+      if (templateIterator != null) {
+        templateIterator.abandon();
+        child._templateIterator = null;
+      }
+    }
+    child.remove();
+    _removeAllBindingsRecursively(child);
+  }
 }
 
 class _BindingToken {
@@ -549,77 +632,6 @@
   bool get isText => !isBinding;
 }
 
-List<_BindingToken> _parseMustacheTokens(String s) {
-  var result = [];
-  var length = s.length;
-  var index = 0, lastIndex = 0;
-  while (lastIndex < length) {
-    index = s.indexOf('{{', lastIndex);
-    if (index < 0) {
-      result.add(new _BindingToken(s.substring(lastIndex)));
-      break;
-    } else {
-      // There is a non-empty text run before the next path token.
-      if (index > 0 && lastIndex < index) {
-        result.add(new _BindingToken(s.substring(lastIndex, index)));
-      }
-      lastIndex = index + 2;
-      index = s.indexOf('}}', lastIndex);
-      if (index < 0) {
-        var text = s.substring(lastIndex - 2);
-        if (result.length > 0 && result.last.isText) {
-          result.last.value += text;
-        } else {
-          result.add(new _BindingToken(text));
-        }
-        break;
-      }
-
-      var value = s.substring(lastIndex, index).trim();
-      result.add(new _BindingToken(value, isBinding: true));
-      lastIndex = index + 2;
-    }
-  }
-  return result;
-}
-
-void _addTemplateInstanceRecord(fragment, model) {
-  if (fragment.$dom_firstChild == null) {
-    return;
-  }
-
-  var instanceRecord = new TemplateInstance(
-      fragment.$dom_firstChild, fragment.$dom_lastChild, model);
-
-  var node = instanceRecord.firstNode;
-  while (node != null) {
-    node._templateInstance = instanceRecord;
-    node = node.nextNode;
-  }
-}
-
-void _removeAllBindingsRecursively(Node node) {
-  node.unbindAll();
-  for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-    _removeAllBindingsRecursively(c);
-  }
-}
-
-void _removeTemplateChild(Node parent, Node child) {
-  child._templateInstance = null;
-  if (child is Element && child.isTemplate) {
-    // Make sure we stop observing when we remove an element.
-    var templateIterator = child._templateIterator;
-    if (templateIterator != null) {
-      templateIterator.abandon();
-      child._templateIterator = null;
-    }
-  }
-  child.remove();
-  _removeAllBindingsRecursively(child);
-}
-
-
 class _TemplateIterator {
   final Element _templateElement;
   final List<Node> terminators = [];
@@ -636,7 +648,7 @@
   }
 
   static Object resolveInputs(Map values) {
-    if (values.containsKey('if') && !_templateBooleanConversion(values['if'])) {
+    if (values.containsKey('if') && !_Bindings._toBoolean(values['if'])) {
       return null;
     }
 
@@ -697,7 +709,7 @@
     while (terminator != previousTerminator) {
       var node = terminator;
       terminator = node.previousNode;
-      _removeTemplateChild(parent, node);
+      _Bindings._removeChild(parent, node);
     }
   }
 
@@ -712,7 +724,7 @@
     while (terminator != previousTerminator) {
       var node = terminator;
       terminator = node.previousNode;
-      _removeTemplateChild(parent, node);
+      _Bindings._removeChild(parent, node);
     }
   }
 
@@ -754,8 +766,8 @@
 
         var fragment = getInstanceFragment(syntax);
 
-        _addBindings(fragment, model, syntax);
-        _addTemplateInstanceRecord(fragment, model);
+        _Bindings._addBindings(fragment, model, syntax);
+        _Bindings._addTemplateInstanceRecord(fragment, model);
 
         insertInstanceAt(addIndex, fragment);
       }
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 9021a7d..28e1d55 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -25,6 +25,7 @@
 import 'dart:web_gl' as gl;
 import 'dart:web_sql';
 import 'dart:_js_helper' show convertDartClosureToJS, Creates, JavaScriptIndexingBehavior, JSName, Null, Returns;
+import 'dart:_interceptors' show Interceptor;
 import 'dart:_isolate_helper' show IsolateNatives;
 import 'dart:_foreign_helper' show JS;
 
diff --git a/tools/dom/templates/html/dart2js/impl_URL.darttemplate b/tools/dom/templates/html/dart2js/impl_URL.darttemplate
index 1a02aa1..30c4161 100644
--- a/tools/dom/templates/html/dart2js/impl_URL.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_URL.darttemplate
@@ -8,11 +8,11 @@
 
   static String createObjectUrl(blob_OR_source_OR_stream) =>
       JS('String',
-         '(window.URL || window.webkitURL).createObjectURL(#)',
+         '(self.URL || self.webkitURL).createObjectURL(#)',
          blob_OR_source_OR_stream);
 
   static void revokeObjectUrl(String objectUrl) =>
       JS('void',
-         '(window.URL || window.webkitURL).revokeObjectURL(#)', objectUrl);
+         '(self.URL || self.webkitURL).revokeObjectURL(#)', objectUrl);
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/dart2js/svg_dart2js.darttemplate b/tools/dom/templates/html/dart2js/svg_dart2js.darttemplate
index 2f001d2..c5fd5e2 100644
--- a/tools/dom/templates/html/dart2js/svg_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/svg_dart2js.darttemplate
@@ -11,7 +11,7 @@
 import 'dart:html_common';
 import 'dart:_js_helper' show Creates, Returns, JavaScriptIndexingBehavior, JSName;
 import 'dart:_foreign_helper' show JS;
-
+import 'dart:_interceptors' show Interceptor;
 
 part '$AUXILIARY_DIR/shared_SVGFactoryProviders.dart';
 
diff --git a/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate
index e9e62f3..c7b04f6 100644
--- a/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate
@@ -12,5 +12,6 @@
 import 'dart:typed_data';
 import 'dart:_js_helper' show Creates, Returns, convertDartClosureToJS;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show Interceptor;
 
 $!GENERATED_DART_FILES
diff --git a/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate
index bb5c1ea..ad41aba 100644
--- a/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate
@@ -11,6 +11,7 @@
 import 'dart:typed_data';
 import 'dart:_js_helper' show Creates, JSName, Null, Returns, convertDartClosureToJS;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show Interceptor;
 
 part '$AUXILIARY_DIR/WebGLConstants.dart';
 
diff --git a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
index 6e50a6e05..ba02215 100644
--- a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
@@ -21,5 +21,6 @@
 import 'dart:html_common';
 import 'dart:_js_helper' show convertDartClosureToJS, Creates, JavaScriptIndexingBehavior, JSName;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show Interceptor;
 
 $!GENERATED_DART_FILES
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index 0d0a233..90fb83a 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -17,9 +17,13 @@
   }
 
 $if DART2JS
+  @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
     // try/catch for IE9 which throws on unsupported values.
     try {
+      if (priority == null) {
+        priority = '';
+      }
       JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
       // Bug #2772, IE9 requires a poke to actually apply the value.
       if (JS('bool', '!!#.setAttribute', this)) {
@@ -43,6 +47,14 @@
    * Checks to see if CSS Transitions are supported.
    */
   static bool get supportsTransitions => true;
+
+  @DomName('CSSStyleDeclaration.setProperty')
+  void setProperty(String propertyName, String value, [String priority]) {
+    if (priority == null) {
+      priority = '';
+    }
+    _setProperty(propertyName, value, priority);
+  }
 $endif
 
   // TODO(jacobr): generate this list of properties using the existing script.
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index e4faf0c..261a6cd 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -424,20 +424,31 @@
   void onCreated() {}
 
   // Hooks to support custom WebComponents.
+
+$if DART2JS
+  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
+$endif
+  Element _xtag;
+
   /**
    * Experimental support for [web components][wc]. This field stores a
    * reference to the component implementation. It was inspired by Mozilla's
    * [x-tags][] project. Please note: in the future it may be possible to
    * `extend Element` from your class, in which case this field will be
-   * deprecated and will simply return this [Element] object.
+   * deprecated.
+   *
+   * If xtag has not been set, it will simply return `this` [Element].
    *
    * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html
    * [x-tags]: http://x-tags.org/
    */
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  var xtag;
+  // Note: return type is `dynamic` for convenience to suppress warnings when
+  // members of the component are used. The actual type is a subtype of Element.
+  get xtag => _xtag != null ? _xtag : this;
+
+  void set xtag(Element value) {
+    _xtag = value;
+  }
 
   /**
    * Scrolls this element into view.
@@ -674,24 +685,24 @@
       self._attributeBindings = new Map<String, StreamSubscription>();
     }
 
-    self.attributes.remove(name);
+    self.xtag.attributes.remove(name);
 
     var changed;
     if (name.endsWith('?')) {
       name = name.substring(0, name.length - 1);
 
       changed = (value) {
-        if (_templateBooleanConversion(value)) {
-          self.attributes[name] = '';
+        if (_Bindings._toBoolean(value)) {
+          self.xtag.attributes[name] = '';
         } else {
-          self.attributes.remove(name);
+          self.xtag.attributes.remove(name);
         }
       };
     } else {
       changed = (value) {
         // TODO(jmesserly): escape value if needed to protect against XSS.
-        // See https://github.com/toolkitchen/mdv/issues/58
-        self.attributes[name] = value == null ? '' : '$value';
+        // See https://github.com/polymer-project/mdv/issues/58
+        self.xtag.attributes[name] = value == null ? '' : '$value';
       };
     }
 
@@ -814,8 +825,8 @@
     var template = ref;
     if (template == null) template = this;
 
-    var instance = _createDeepCloneAndDecorateTemplates(template.content,
-        attributes['syntax']);
+    var instance = _Bindings._createDeepCloneAndDecorateTemplates(
+        template.content, attributes['syntax']);
 
     if (TemplateElement._instanceCreated != null) {
       TemplateElement._instanceCreated.add(instance);
@@ -841,7 +852,7 @@
 
     var syntax = TemplateElement.syntax[attributes['syntax']];
     _model = value;
-    _addBindings(this, model, syntax);
+    _Bindings._addBindings(this, model, syntax);
   }
 
   // TODO(jmesserly): const set would be better
diff --git a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
index a8459d1..42f8d38 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
@@ -55,7 +55,7 @@
 
     // Create content
     if (template is! TemplateElement) {
-      var doc = _getTemplateContentsOwner(template.document);
+      var doc = _Bindings._getTemplateContentsOwner(template.document);
       template._templateContent = doc.createDocumentFragment();
     }
 
@@ -65,9 +65,9 @@
     }
 
     if (template is TemplateElement) {
-      _bootstrapTemplatesRecursivelyFrom(template.content);
+      bootstrap(template.content);
     } else {
-      _liftNonNativeTemplateChildrenIntoContent(template);
+      _Bindings._liftNonNativeChildrenIntoContent(template);
     }
 
     return true;
@@ -83,7 +83,23 @@
   // TODO(rafaelw): Review whether this is the right public API.
   @Experimental
   static void bootstrap(Node content) {
-    _bootstrapTemplatesRecursivelyFrom(content);
+    _Bindings._bootstrapTemplatesRecursivelyFrom(content);
+  }
+
+  /**
+   * Binds all mustaches recursively starting from the [root] node.
+   *
+   * Note: this is not an official Model-Driven-Views API; it is intended to
+   * support binding the [ShadowRoot]'s content to a model.
+   */
+  // TODO(jmesserly): this is needed to avoid two <template> nodes when using
+  // bindings in a custom element's template. See also:
+  // https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
+  // Called from:
+  // https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
+  @Experimental
+  static void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
+    _Bindings._addBindings(root, model, syntax);
   }
 
   static bool _initStyles;
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 7ae7698..b1fee6e 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -78,7 +78,8 @@
    * See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access_authentication).
    */
   static Future<HttpRequest> request(String url,
-      {String method, bool withCredentials, String responseType, sendData,
+      {String method, bool withCredentials, String responseType,
+      String mimeType, Map<String, String> requestHeaders, sendData,
       void onProgress(ProgressEvent e)}) {
     var completer = new Completer<HttpRequest>();
 
@@ -96,6 +97,16 @@
       xhr.responseType = responseType;
     }
 
+    if (mimeType != null) {
+      xhr.overrideMimeType(mimeType);
+    }
+
+    if (requestHeaders != null) {
+      requestHeaders.forEach((header, value) {
+        xhr.setRequestHeader(header, value);
+      });
+    }
+
     if (onProgress != null) {
       xhr.onProgress.listen(onProgress);
     }
@@ -163,5 +174,18 @@
 $endif
   }
 
+  /**
+   * Checks to see if the overrideMimeType method is supported on the current
+   * platform.
+   */
+  static bool get supportsOverrideMimeType {
+$if DART2JS
+    var xhr = new HttpRequest();
+    return JS('bool', '("overrideMimeType" in #)', xhr);
+$else
+    return true;
+$endif
+  }
+
 $!MEMBERS
 }
diff --git a/tools/dom/templates/immutable_list_mixin.darttemplate b/tools/dom/templates/immutable_list_mixin.darttemplate
index e9bffe5..fc48b49 100644
--- a/tools/dom/templates/immutable_list_mixin.darttemplate
+++ b/tools/dom/templates/immutable_list_mixin.darttemplate
@@ -12,4 +12,41 @@
   }
 $endif
 
+  $E get first {
+    if (this.length > 0) {
+$if DART2JS
+      return JS('$E', '#[0]', this);
+$else
+      return this[0];
+$endif
+    }
+    throw new StateError("No elements");
+  }
+
+  $E get last {
+    int len = this.length;
+    if (len > 0) {
+$if DART2JS
+      return JS('$E', '#[#]', this, len - 1);
+$else
+      return this[len - 1];
+$endif
+    }
+    throw new StateError("No elements");
+  }
+
+  $E get single {
+    int len = this.length;
+    if (len == 1) {
+$if DART2JS
+      return JS('$E', '#[0]', this);
+$else
+      return this[0];
+$endif
+    }
+    if (len == 0) throw new StateError("No elements");
+    throw new StateError("More than one element");
+  }
+
+  $E elementAt(int index) => this[index];
   // -- end List<$E> mixins.
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
new file mode 100644
index 0000000..0912d23
--- /dev/null
+++ b/tools/testing/dart/browser_controller.dart
@@ -0,0 +1,693 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+library browser;
+
+import "dart:async";
+import "dart:core";
+import "dart:io";
+
+
+/** Class describing the interface for communicating with browsers. */
+class Browser {
+  // Browsers actually takes a while to cleanup after itself when closing
+  // Give it sufficient time to do that.
+  static final Duration killRepeatInternal = const Duration(seconds: 10);
+  static final int killRetries = 5;
+  StringBuffer _stdout = new StringBuffer();
+  StringBuffer _stderr = new StringBuffer();
+  StringBuffer _usageLog = new StringBuffer();
+  // This function is called when the process is closed.
+  // This is extracted to an external function so that we can do additional
+  // functionality when the process closes (cleanup and call onExit)
+  Function _processClosed;
+  // This is called after the process is closed, after _processClosed has
+  // been called, but before onExit. Subclasses can use this to cleanup
+  // any browser specific resources (temp directories, profiles, etc)
+  Function _cleanup;
+
+  /** The version of the browser - normally set when starting a browser */
+  String version = "";
+  /**
+   * The underlying process - don't mess directly with this if you don't
+   * know what you are doing (this is an interactive process that needs
+   * special threatment to not leak).
+   */
+  Process process;
+
+  /**
+   * Id of the browser
+   */
+  String id;
+
+  /** Callback that will be executed when the browser has closed */
+  Function onClose;
+
+  /** Print everything (stdout, stderr, usageLog) whenever we add to it */
+  bool debugPrint = true;
+
+  void _logEvent(String event) {
+    String toLog = "$this ($id) - ${new DateTime.now()}: $event \n";
+    if (debugPrint) print("usageLog: $toLog");
+    _usageLog.write(toLog);
+  }
+
+  void _addStdout(String output) {
+    if (debugPrint) print("stdout: $output");
+    _stdout.write(output);
+  }
+
+  void _addStderr(String output) {
+    if (debugPrint) print("stderr: $output");
+    _stderr.write(output);
+  }
+
+  // Kill the underlying process using the supplied kill function
+  // If there is a alternativeKillFunction we will use that after trying
+  // the default killFunction.
+  Future _killIt(killFunction, retries, [alternativeKillFunction = null]) {
+    Completer<bool> completer = new Completer<bool>();
+
+    // To capture non successfull attempts we set up a timer that will
+    // trigger a retry (using the alternativeKillFunction if supplied).
+    Timer timer =  new Timer(killRepeatInternal, () {
+      // Remove the handler, we will set this again in the call to killIt
+      // below
+      if (retries <= 0) {
+        _logEvent("Could not kill the process, not trying anymore");
+        // TODO(ricow): Should we crash the test script here and
+        // write out all our log. This is basically not a situation
+        // that we want to ignore. We could potentially have a handler we
+        // can call if this happens, which will shutdown the main process
+        // with info that people should contact [ricow,kustermann,?]
+        completer.complete(false);
+      }
+      _logEvent("Could not kill the process, retrying");
+      var nextKillFunction = killFunction;
+      if (alternativeKillFunction != null) {
+        nextKillFunction = alternativeKillFunction;
+      }
+      _killIt(nextKillFunction, retries - 1).then((success) {
+        completer.complete(success);
+      });
+    });
+
+    // Make sure we intercept onExit calls and eliminate the timer.
+    _processClosed = () {
+      timer.cancel();
+      _logEvent("Proccess exited, cancel timer in kill loop");
+      _processClosed = null;
+      process = null;
+      completer.complete(true);
+    };
+
+
+    _logEvent("calling kill function");
+    if (killFunction()) {
+      // We successfully sent the signal.
+      _logEvent("killing signal sent");
+    } else {
+      _logEvent("The process is already dead, kill signal could not be send");
+      completer.complete(true);
+    }
+    return completer.future;
+  }
+
+
+  /** Close the browser */
+  Future<bool> close() {
+    _logEvent("Close called on browser");
+    if (process == null) {
+      _logEvent("No process open, nothing to kill.");
+      return new Future.immediate(true);
+    }
+    var killFunction = process.kill;
+    // We use a SIGKILL signal if we don't kill the process in the first go.
+    var alternativeKillFunction =
+        () { return process.kill(ProcessSignal.SIGKILL);};
+    return _killIt(killFunction, killRetries, alternativeKillFunction);
+  }
+
+  /**
+   * Start the browser using the supplied argument.
+   * This sets up the error handling and usage logging.
+   */
+  Future<bool> startBrowser(String command, List<String> arguments) {
+    return Process.start(command, arguments).then((startedProcess) {
+      process = startedProcess;
+      process.stdout.transform(new StringDecoder()).listen((data) {
+        _addStdout(data);
+      }, onError: (error) {
+        // This should _never_ happen, but we really want this in the log
+        // if it actually does due to dart:io or vm bug.
+        _usageLog.add(
+            "An error occured in the process stdout handling: $error");
+      });
+
+      process.stderr.transform(new StringDecoder()).listen((data) {
+        _addStderr(data);
+      }, onError: (error) {
+        // This should _never_ happen, but we really want this in the log
+        // if it actually does due to dart:io or vm bug.
+        _usageLog.add(
+            "An error occured in the process stderr handling: $error");
+      });
+
+      process.exitCode.then((exitCode) {
+        _logEvent("Browser closed with exitcode $exitCode");
+        if (_processClosed != null) _processClosed();
+        if (_cleanup != null) _cleanup();
+        if (onClose != null) onClose(exitCode);
+      });
+      return true;
+    }).catchError((error) {
+      _logEvent("Running $binary $arguments failed with $error");
+      return false;
+    });
+  }
+
+  /**
+   * Get any stdout that the browser wrote during execution.
+   */
+  String get stdout => _stdout.toString();
+  String get stderr => _stderr.toString();
+  String get usageLog => _usageLog.toString();
+
+  String toString();
+  /** Starts the browser loading the given url */
+  Future<bool> start(String url);
+}
+
+
+class Chrome extends Browser {
+  /**
+   * The binary used to run chrome - changing this can be nececcary for
+   * testing or using non standard chrome installation.
+   */
+  const String binary = "google-chrome";
+
+  Future<bool> start(String url) {
+    _logEvent("Starting chrome browser on: $url");
+    // Get the version and log that.
+    return Process.run(binary, ["--version"]).then((var versionResult) {
+      if (versionResult.exitCode != 0) {
+        _logEvent("Failed to chrome get version");
+        _logEvent("Make sure $binary is a valid program for running chrome");
+        return new Future.immediate(false);
+      }
+      version = versionResult.stdout;
+      _logEvent("Got version: $version");
+
+      return new Directory('').createTemp().then((userDir) {
+        _cleanup = () { userDir.delete(recursive: true); };
+        var args = ["--user-data-dir=${userDir.path}", url,
+                    "--disable-extensions", "--disable-popup-blocking",
+                    "--bwsi"];
+        return startBrowser(binary, args);
+
+      });
+    }).catchError((e) {
+      _logEvent("Running $binary --version failed with $e");
+      return false;
+    });
+  }
+
+  String toString() => "Chrome";
+}
+
+class Firefox extends Browser {
+  /**
+   * The binary used to run firefox - changing this can be nececcary for
+   * testing or using non standard firefox installation.
+   */
+  const String binary = "firefox";
+
+  const String enablePopUp =
+      "user_pref(\"dom.disable_open_during_load\", false);";
+
+  Future _createPreferenceFile(var path) {
+    var file = new File("${path.toString()}/user.js");
+    var randomFile = file.openSync(FileMode.WRITE);
+    randomFile.writeStringSync(enablePopUp);
+    randomFile.close();
+  }
+
+
+  Future<bool> start(String url) {
+    _logEvent("Starting firefox browser on: $url");
+    // Get the version and log that.
+    return Process.run(binary, ["--version"]).then((var versionResult) {
+      if (versionResult.exitCode != 0) {
+        _logEvent("Failed to firefox get version");
+        _logEvent("Make sure $binary is a valid program for running firefox");
+        return new Future.immediate(false);
+      }
+      version = versionResult.stdout;
+      _logEvent("Got version: $version");
+
+      return new Directory('').createTemp().then((userDir) {
+        _createPreferenceFile(userDir.path);
+        _cleanup = () { userDir.delete(recursive: true); };
+        var args = ["-profile", "${userDir.path}",
+                    "-no-remote", "-new-instance", url];
+        return startBrowser(binary, args);
+
+      });
+    }).catchError((e) {
+      _logEvent("Running $binary --version failed with $e");
+      return false;
+    });
+  }
+
+  String toString() => "Firefox";
+}
+
+
+/**
+ * Describes the current state of a browser used for testing.
+ */
+class BrowserTestingStatus {
+// TODO(ricow): Add prefetching to the browsers. We spend a lot of time waiting
+// for the next test. Handling timeouts is the hard part of this!
+
+
+  Browser browser;
+  BrowserTest currentTest;
+  // This is currently not used for anything except for error reporting.
+  // Given the usefulness of this in debugging issues this should not be
+  // removed even when we have really stable system.
+  BrowserTest lastTest;
+  bool timeout = false;
+  BrowserTestingStatus(Browser this.browser);
+}
+
+
+/**
+ * Describes a single test to be run int the browser.
+ */
+class BrowserTest {
+  // TODO(ricow): Add timeout callback instead of the string passing hack.
+  Function doneCallback;
+  String url;
+  int timeout;
+  // We store this here for easy access when tests time out (instead of
+  // capturing this in a closure)
+  Timer timeoutTimer;
+
+  // Used for debugging, this is simply a unique identifier assigned to each
+  // test.
+  int id;
+  static int _idCounter = 0;
+
+  BrowserTest(this.url, this.doneCallback, this.timeout) {
+    id = _idCounter++;
+  }
+}
+
+
+/**
+ * Encapsulates all the functionality for running tests in browsers.
+ * The interface is rather simple. After starting the runner tests
+ * are simply added to the queue and a the supplied callbacks are called
+ * whenever a test completes.
+ */
+class BrowserTestRunner {
+  int maxNumBrowsers;
+  String browserName;
+
+  bool underTermination = false;
+
+  List<BrowserTest> testQueue = new List<BrowserTest>();
+  Map<String, BrowserTestingStatus> browserStatus =
+      new Map<String, BrowserTestingStatus>();
+  // This cache is used to guarantee that we never see double reporting.
+  // If we do we need to provide developers with this information.
+  // We don't add urls to the cache until we have run it.
+  Map<int, String> testCache = new Map<int, String>();
+  List<int> doubleReportingTests = new List<int>();
+
+  BrowserTestingServer testingServer;
+
+  BrowserTestRunner(String this.browserName, int this.maxNumBrowsers);
+
+  Future<bool> start() {
+    testingServer = new BrowserTestingServer();
+    return testingServer.start().then((_) {
+      testingServer.testDoneCallBack = handleResults;
+      testingServer.nextTestCallBack = getNextTest;
+      var futures = [];
+      for (int i = 0; i < maxNumBrowsers; i++) {
+        var browser = getInstance();
+        var id = "BROWSER$i";
+        // We store this in case we need to kill the browser.
+        browser.id = id;
+        var future =
+            browser.start(testingServer.getDriverUrl(id)).then((success) {
+              if (success) {
+                browserStatus[id] = new BrowserTestingStatus(browser);
+              }
+              return success;
+            });
+        futures.add(future);
+      }
+      return Future.wait(futures).then((values) {
+        return !values.contains(false);
+      });
+    });
+  }
+
+  var timedOut = [];
+
+  void handleResults(String browserId, String output, int testId) {
+    var status = browserStatus[browserId];
+    if (testCache.containsKey(testId)) {
+      doubleReportingTests.add(testId);
+      return;
+    }
+
+    if (status.timeout) {
+      // We don't do anything, this browser is currently being killed and
+      // replaced.
+    } else if (status.currentTest != null) {
+      status.currentTest.timeoutTimer.cancel();
+      if (status.currentTest.id != testId) {
+        print("Expected test id ${status.currentTest.id} for"
+              "${status.currentTest.url}");
+        print("Got test id ${testId}");
+        print("Last test id was ${status.lastTest.id} for "
+              "${status.currentTest.url}");
+        throw("This should never happen, wrong test id");
+      }
+      testCache[testId] = status.currentTest.url;
+      status.currentTest.doneCallback(output);
+      status.lastTest = status.currentTest;
+      status.currentTest = null;
+    } else {
+      print("\nThis is bad, should never happen, handleResult no test");
+      print("URL: ${status.lastTest.url}");
+      print(output);
+      terminate().then((_) {
+        exit(1);
+      });
+    }
+  }
+
+  void handleTimeout(BrowserTestingStatus status) {
+    // We simply kill the browser and starts up a new one!
+    // We could be smarter here, but it does not seems like it is worth it.
+    status.timeout = true;
+    timedOut.add(status.currentTest.url);
+    var id = status.browser.id;
+    status.browser.close().then((closed) {
+      if (!closed) {
+        // Very bad, we could not kill the browser.
+        print("could not kill browser $id");
+        return;
+      }
+      // Start the new browser first
+      var browser = getInstance();
+      browser.start(testingServer.getDriverUrl(id)).then((success) {
+        // We may have started terminating in the mean time.
+        if (underTermination) {
+          browser.close().then((success) {
+            // We should never hit this, print it out.
+            if (!success) {
+              print("Could not kill browser ($id) started due to timeout");
+            }
+          });
+          return;
+        }
+        if (success) {
+          browser.id = id;
+          status.browser = browser;
+          status.timeout = false;
+        } else {
+          // TODO(ricow): Handle this better.
+          print("This is bad, should never happen, could not start browser");
+          exit(1);
+        }
+      });
+    });
+
+    status.currentTest.doneCallback("TIMEOUT");
+    status.currentTest = null;
+  }
+
+  BrowserTest getNextTest(String browserId) {
+    if (testQueue.isEmpty) return null;
+    var status = browserStatus[browserId];
+    if (status == null) return null;
+    // We are currently terminating this browser, don't start a new test.
+    if (status.timeout) return null;
+    BrowserTest test = testQueue.removeLast();
+    if (status.currentTest == null) {
+      status.currentTest = test;
+    } else {
+      // TODO(ricow): Handle this better.
+      print("This is bad, should never happen, getNextTest all full");
+      print("Old test was: ${status.currentTest.url}");
+      print("Timed out tests:");
+      for (var v in timedOut) {
+        print("  $v");
+      }
+      exit(1);
+    }
+    Timer timer = new Timer(new Duration(seconds: test.timeout),
+                            () { handleTimeout(status); });
+    status.currentTest.timeoutTimer = timer;
+    return test;
+  }
+
+  void queueTest(BrowserTest test) {
+    testQueue.add(test);
+  }
+
+  void printDoubleReportingTests() {
+    if (doubleReportingTests.length == 0) return;
+    // TODO(ricow): die on double reporting.
+    // Currently we just report this here, we could have a callback to the
+    // encapsulating environment.
+    print("");
+    print("Double reporting tests");
+    for (var id in doubleReportingTests) {
+      print("  ${testCache[id]}");
+    }
+  }
+
+  Future<bool> terminate() {
+    var futures = [];
+    underTermination = true;
+    testingServer.underTermination = true;
+    for (BrowserTestingStatus status in browserStatus.values) {
+      futures.add(status.browser.close());
+    }
+    return Future.wait(futures).then((values) {
+      testingServer.httpServer.close();
+      printDoubleReportingTests();
+      return !values.contains(false);
+    });
+  }
+
+  Browser getInstance() {
+    if (browserName == "chrome") {
+      return new Chrome();
+    } else if (browserName == "firefox") {
+      return new Firefox();
+    }
+    throw "Non supported browser for browser controller";
+  }
+}
+
+class BrowserTestingServer {
+  const String server = "127.0.0.1";
+
+  /// Interface of the testing server:
+  ///
+  /// GET /driver/BROWSER_ID -- This will get the driver page to fetch
+  ///                           and run tests ...
+  /// GET /next_test/BROWSER_ID -- returns "WAIT" "TERMINATE" or "url#id"
+  /// where url is the test to run, and id is the id of the test.
+  /// If there are currently no available tests the waitSignal is send
+  /// back. If we are in the process of terminating the terminateSignal
+  /// is send back and the browser will stop requesting new tasks.
+  /// POST /report/BROWSER_ID?id=NUM -- sends back the dom of the executed
+  ///                                   test
+
+
+  const String driverPath = "/driver";
+  const String nextTestPath = "/next_test";
+  const String reportPath = "/report";
+  const String waitSignal = "WAIT";
+  const String terminateSignal = "TERMINATE";
+
+  var testCount = 0;
+  var httpServer;
+  bool underTermination = false;
+
+  Function testDoneCallBack;
+  Function nextTestCallBack;
+
+  Future start() {
+    return HttpServer.bind(server, 0).then((createdServer) {
+      httpServer = createdServer;
+      void handler(HttpRequest request) {
+        if (request.uri.path.startsWith(reportPath)) {
+          var browserId = request.uri.path.substring(reportPath.length + 1);
+          var testId = int.parse(request.queryParameters["id"].split("=")[1]);
+
+          handleReport(request, browserId, testId);
+          // handleReport will asynchroniously fetch the data and will handle
+          // the closing of the streams.
+          return;
+        }
+        var textResponse = "";
+        if (request.uri.path.startsWith(driverPath)) {
+          var browserId = request.uri.path.substring(driverPath.length + 1);
+          textResponse = getDriverPage(browserId);
+        } else if (request.uri.path.startsWith(nextTestPath)) {
+          var browserId = request.uri.path.substring(nextTestPath.length + 1);
+          textResponse = getNextTest(browserId);
+        } else {
+          // We silently ignore other requests.
+        }
+        request.response.write(textResponse);
+        request.listen((_) {}, onDone: request.response.close);
+        request.response.done.catchError((error) {
+        if (!underTermination) {
+          print("URI ${request.uri}");
+          print("Textresponse $textResponse");
+          throw("Error returning content to browser: $error");
+        }
+      });
+      }
+      void errorHandler(e) {
+        if (!underTermination) print("Error occured in httpserver: $e");
+      };
+      httpServer.listen(handler, onError: errorHandler);
+      return true;
+    });
+  }
+
+  void handleReport(HttpRequest request, String browserId, var testId) {
+    StringBuffer buffer = new StringBuffer();
+    request.transform(new StringDecoder()).listen((data) {
+      buffer.write(data);
+      }, onDone: () {
+        String back = buffer.toString();
+        request.response.close();
+        testDoneCallBack(browserId, back, testId);
+      }, onError: (error) { print(error); });
+  }
+
+  String getNextTest(String browserId) {
+    var nextTest = nextTestCallBack(browserId);
+    if (underTermination) {
+      // Browsers will be killed shortly, send them a terminate signal so
+      // that they stop pulling.
+      return terminateSignal;
+    } else if (nextTest == null) {
+      // We don't currently have any tests ready for consumption, wait.
+      return waitSignal;
+    } else {
+      return "${nextTest.url}#id=${nextTest.id}";
+    }
+  }
+
+  String getDriverUrl(String browserId) {
+    if (httpServer == null) {
+      print("Bad browser testing server, you are not started yet. Can't "
+            "produce driver url");
+      exit(1);
+      // This should never happen - exit immediately;
+    }
+    return "http://$server:${httpServer.port}/driver/$browserId";
+  }
+
+
+  String getDriverPage(String browserId) {
+    String driverContent = """
+<!DOCTYPE html><html>
+<head>
+  <title>Driving page</title>
+  <script type='text/javascript'>
+    var numberOfTests = 0;
+    var currentId;
+    var testing_window;
+
+    function newTaskHandler() {
+      if (this.readyState == this.DONE) {
+        if (this.status == 200) {
+          if (this.responseText == '$waitSignal') {
+            setTimeout(getNextTask, 500);
+          } else if (this.responseText == '$terminateSignal') {
+            // Don't do anything, we will be killed shortly.
+          } else {
+            // TODO(ricow): Do something more clever here.
+            if (nextTask != undefined) alert('This is really bad');
+            // The task is send to us as:
+            // URL#ID
+            var split = this.responseText.split('#');
+            var nextTask = split[0];
+            id = split[1];
+            run(nextTask);
+          }
+        } else {
+          // We are basically in trouble - do something clever.
+        }
+      }
+    }
+
+    function getNextTask() {
+      var client = new XMLHttpRequest();
+      client.onreadystatechange = newTaskHandler;
+      client.open('GET', '$nextTestPath/$browserId');
+      client.send();
+    }
+
+    function run(url) {
+      numberOfTests++;
+      document.getElementById('number').innerHTML = numberOfTests;
+      if (testing_window == undefined) {
+        testing_window = window.open(url);
+      } else {
+        testing_window.location = url;
+      }
+    }
+
+    function reportMessage(msg) {
+      var client = new XMLHttpRequest();
+      function handleReady() {
+        if (this.readyState == this.DONE) {
+          getNextTask();
+        }
+      }
+      client.onreadystatechange = handleReady;
+      client.open('POST', '$reportPath/${browserId}?id=' + id);
+      client.setRequestHeader('Content-type',
+                              'application/x-www-form-urlencoded');
+      client.send(msg);
+      // TODO(ricow) add error handling to somehow report the fact that
+      // we could not send back a result.
+    }
+
+    function messageHandler(e) {
+      var msg = e.data;
+      if (typeof msg != 'string') return;
+      reportMessage(msg);
+    }
+
+    window.addEventListener('message', messageHandler, false);
+    waitForDone = false;
+
+    getNextTask();
+
+  </script>
+</head>
+  <body>
+    Dart test driver, number of tests: <div id="number"></div>
+  </body>
+</html>
+""";
+    return driverContent;
+  }
+}
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 6d2453e..a31b093 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -301,6 +301,14 @@
               [],
               false,
               'bool'
+              ),
+          new _TestOptionSpecification(
+              'use_browser_controller',
+              'Use the new selenium replacement browser-controller.',
+              ['--use_browser_controller'],
+              [],
+              false,
+              'bool'
               ),];
   }
 
@@ -508,12 +516,12 @@
       configuration['progress'] = 'verbose';
     }
 
-    // Create the artificial 'unchecked' options that test status files
+    // Create the artificial negative options that test status files
     // expect.
     configuration['unchecked'] = !configuration['checked'];
     configuration['host_unchecked'] = !configuration['host_checked'];
-
     configuration['unminified'] = !configuration['minified'];
+    configuration['nocsp'] = !configuration['csp'];
 
     String runtime = configuration['runtime'];
     if (runtime == 'firefox') {
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 231cdb5..4261cec 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -18,6 +18,7 @@
 import "dart:io" as io;
 import "dart:isolate";
 import "dart:uri";
+import "browser_controller.dart";
 import "http_server.dart" as http_server;
 import "status_file_parser.dart";
 import "test_progress.dart";
@@ -29,6 +30,8 @@
 
 const int CRASHING_BROWSER_EXITCODE = -10;
 
+const int NUMBER_OF_BROWSERCONTROLLER_BROWSERS = 4;
+
 typedef void TestCaseEvent(TestCase testCase);
 typedef void ExitCodeEvent(int exitCode);
 typedef void EnqueueMoreWork(ProcessQueue queue);
@@ -348,6 +351,8 @@
 
   bool get usesWebDriver => TestUtils.usesWebDriver(configuration['runtime']);
 
+  bool get usesBrowserController => configuration['use_browser_controller'];
+
   void completed() { completedHandler(this); }
 
   bool get isFlaky {
@@ -526,7 +531,17 @@
                                      List<int> stderr,
                                      Duration time,
                                      bool compilationSkipped) {
-    if (testCase is BrowserTestCase) {
+    if (testCase.usesBrowserController) {
+      return new HTMLBrowserCommandOutputImpl(testCase,
+                                              command,
+                                              exitCode,
+                                              incomplete,
+                                              timedOut,
+                                              stdout,
+                                              stderr,
+                                              time,
+                                              compilationSkipped);
+    } else if (testCase is BrowserTestCase) {
       return new BrowserCommandOutputImpl(testCase,
                                           command,
                                           exitCode,
@@ -746,6 +761,36 @@
   }
 }
 
+class HTMLBrowserCommandOutputImpl extends BrowserCommandOutputImpl {
+ HTMLBrowserCommandOutputImpl(
+      testCase,
+      command,
+      exitCode,
+      incomplete,
+      timedOut,
+      stdout,
+      stderr,
+      time,
+      compilationSkipped) :
+    super(testCase,
+          command,
+          exitCode,
+          incomplete,
+          timedOut,
+          stdout,
+          stderr,
+          time,
+          compilationSkipped);
+
+  bool get _browserTestFailure {
+    // We should not need to convert back and forward.
+    var output = decodeUtf8(super.stdout);
+    if (output.contains("FAIL")) return true;
+    return !output.contains("PASS");
+  }
+}
+
+
 // The static analyzer does not actually execute code, so
 // the criteria for success now depend on the text sent
 // to stderr.
@@ -1295,6 +1340,8 @@
   // system, generate tests, and search test files for options.
   Map<String, List<TestInformation>> _testCache;
 
+  Map<String, BrowserTestRunner> _browserTestRunners;
+
   /**
    * String indicating the browser used to run the tests. Empty if no browser
    * used.
@@ -1325,7 +1372,8 @@
         _listTests = listTests,
         _tests = new Queue<TestCase>(),
         _batchProcesses = new Map<String, List<BatchRunnerProcess>>(),
-        _testCache = new Map<String, List<TestInformation>>() {
+        _testCache = new Map<String, List<TestInformation>>(),
+        _browserTestRunners = new Map<String, BrowserTestRunner>() {
     _runTests(testSuites);
   }
 
@@ -1343,7 +1391,9 @@
 
   void _checkDone() {
     if (_allTestsWereEnqueued && _tests.isEmpty && _numProcesses == 0) {
-      _terminateBatchRunners().then((_) => _cleanupAndMarkDone());
+      _terminateBatchRunners().then((_) {
+        _terminateBrowserRunners().then((_) => _cleanupAndMarkDone());
+      });
     }
   }
 
@@ -1506,6 +1556,14 @@
     return Future.wait(futures);
   }
 
+  Future _terminateBrowserRunners() {
+    var futures = [];
+    for (BrowserTestRunner runner in _browserTestRunners.values) {
+      futures.add(runner.terminate());
+    }
+    return Future.wait(futures);
+  }
+
   BatchRunnerProcess _getBatchRunner(TestCase test) {
     // Start batch processes if needed
     var compiler = test.configuration['compiler'];
@@ -1524,8 +1582,53 @@
     throw new Exception('Unable to find inactive batch runner.');
   }
 
+  Future<BrowserTestRunner> _getBrowserTestRunner(TestCase test) {
+    var runtime = test.configuration['runtime'];
+    if (_browserTestRunners[runtime] == null) {
+      var testRunner =
+        new BrowserTestRunner(runtime, NUMBER_OF_BROWSERCONTROLLER_BROWSERS);
+      _browserTestRunners[runtime] = testRunner;
+      return testRunner.start().then((started) {
+        if (started) {
+          return testRunner;
+        }
+        print("Issue starting browser test runner");
+        exit(1);
+      });
+    }
+    return new Future.immediate(_browserTestRunners[runtime]);
+  }
+
+  void _startBrowserControllerTest(var test) {
+    // Get the url.
+    // TODO(ricow): This is not needed when we have eliminated selenium.
+    var nextCommandIndex = test.commandOutputs.keys.length;
+    var url = test.commands[nextCommandIndex].toString().split("--out=")[1];
+    // Remove trailing "
+    url = url.split('"')[0];
+    var callback = (var output) {
+      new CommandOutput.fromCase(test,
+                                 test.commands[nextCommandIndex],
+                                 0,
+                                 false,
+                                 output == "TIMEOUT",
+                                 encodeUtf8(output),
+                                 [],
+                                 const Duration(seconds: 1),
+                                 false);
+      test.completedHandler(test);
+    };
+    BrowserTest browserTest = new BrowserTest(url, callback, test.timeout);
+    _getBrowserTestRunner(test).then((testRunner) {
+      testRunner.queueTest(browserTest);
+    });
+  }
+
   void _tryRunTest() {
     _checkDone();
+    // TODO(ricow): remove most of the hacked selenium code below when
+    // we have eliminated the need.
+
     if (_numProcesses < _maxProcesses && !_tests.isEmpty) {
       TestCase test = _tests.removeFirst();
       if (_listTests) {
@@ -1536,8 +1639,8 @@
         print(fields.join('\t'));
         return;
       }
-      if (test.usesWebDriver && _needsSelenium && !_isSeleniumAvailable || (test
-          is BrowserTestCase && test.waitingForOtherTest)) {
+      if (test.usesWebDriver && _needsSelenium && !_isSeleniumAvailable ||
+          (test is BrowserTestCase && test.waitingForOtherTest)) {
         // The test is not yet ready to run. Put the test back in
         // the queue.  Avoid spin-polling by using a timeout.
         _tests.add(test);
@@ -1598,7 +1701,12 @@
           _tryRunTest();
         };
         test.completedHandler = testCompleted;
-        _getBatchRunner(test).startTest(test);
+
+        if (test.usesBrowserController) {
+          _startBrowserControllerTest(test);
+        } else {
+          _getBatchRunner(test).startTest(test);
+        }
       } else {
         // Once we've actually failed a test, technically, we wouldn't need to
         // bother retrying any subsequent tests since the bot is already red.